![](/img/trans.png)
[英]How do you save changes to navigation properties using Entity Framework
[英]How to correctly save the changes to Entity with Navigation Properties
我正在嘗試編寫PUT-action的正確實現。 我有一個基本的Model類(我們稱它為Model)。
public class Model
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public User Creator { get; set; }
}
創建者是必需的導航屬性,該屬性通過外鍵引用User實體。 另外,我有一個用於我的模型的簡單DTO類,該類正在從客戶端發布。
public class ModelDTO
{
public int Id { get; set; }
public string Name { get; set; }
}
如您所見,DTO類不包含Creator引用,因為我們不需要從客戶端進行更新。
這是PUT動作。 它基於Visual Studio為我提供的模板。 我剛剛添加了Automapper調用以將DTO映射到Model。
// PUT: api/Models/5
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutModel(int id, ModelDTO modelDTO)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != Model.Id)
{
return BadRequest();
}
var model = Mapper.Map<Model>(modelDTO); // i've just added this
db.Entry(model).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ModelExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
問題是SaveChangesAsync方法因Db驗證錯誤“需要創建者字段”而崩潰。 從技術上講,我了解Creator是空的,因為我已經創建了新的Model實例,並且EF不知道我是要將Creator設置為null還是忽略它。 我需要以某種方式聲明我不想設置創建者。 我只想更新Name(或其他將來的標量屬性)。 那么,如何在不加載(包括)導航屬性數據的情況下正確地進行操作呢? 是否有一些常見的最佳實踐方法?
謝謝。
好的,一旦您扔掉了腳手架為您生成的廢話,也許您可以嘗試編寫一些有用的代碼並增加獲得可行解決方案的機會。
您可以從DTO / viewmodel =>擺脫Id
屬性開始,該屬性來自其他地方(路徑段),因此它不應該成為更新視圖模型的一部分:
public class ModelDTO
{
// The name is required => make sure that your DTO
// respects this requirement as well before even
// reaching your backend
[Required]
public string Name { get; set; }
}
太好了,現在您可以繼續為PUT控制器操作編寫代碼:
[HttpPut]
public async Task<IHttpActionResult> Put(int id, ModelDTO modelDTO)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Get the model that you are trying to update from the DB
// using the id:
var model = db.Models.Find(id);
if (model == null)
{
// the id that was provided as parameter doesn't exist in the DB =>
// we don't need to go any further, just let the client know
// by returning 404
return NotFound();
}
// set the properties that you want to update (only Name in your case)
// of course when you have more complex models you might consider using
// AutoMapper to take care of this part, but for the purposes of this
// demonstration you don't need it:
model.Name = modelDTO.Name;
// Now save the changes back to your database
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
好,所以這里要記住的是以下幾點:
當某個工具試圖在自己的位置編寫代碼時,開發人員應該做的第一件事就是簡單地丟棄該工具/代碼,然后開始工作(在開發人員的情況下,就是編寫代碼)。
我只想更新Name(或其他將來的標量屬性)。 那么,如何在不加載(包括)導航屬性數據的情況下正確地進行操作呢? 是否有一些常見的最佳實踐方法?
因此,您想更新一些特定字段,並在情況下更新Name
字段
//// find your model
var entity = db.Models.Find(id);
entity.Name=modelDTO.Name;
/// set modified property
db.Entry(entity).Property(c => c.Name).IsModified = true
await db.SaveChangesAsync();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.