![](/img/trans.png)
[英]How to deal with detached model when trying to update table in Entity Framework
[英].Net Entity Framework Update Detached Children
所以我有例如這些模型:
public class Account
{
public Guid ID {get;set;}
[ForeignKey("Profile")]
public Guid? ProfileId {get;set;}
public virtual Profile Profile {get;set;}
......
}
public class Profile
{
public Guid ID {get;set;}
[ForeignKey("Account")]
public Guid AccountId {get;set;}
public virtual Account Account {get;set;}
}
然后我有一個從 controller 請求的視圖 (html)。
public class ExController : ApiController
{
public async Task<Account> GetAccount(Guid id)
{
return await db.Accounts.Where(m => m.ID == id).FirstOrDefaultAsync();
}
}
然后 html 視圖編輯/更新帳戶實體,然后再次將其傳遞給 controller 以保存到數據庫中。 如果我只是從視圖中保存原始傳遞的實體,則Profile
將被視為新實體。 這不是我想要的,我想要更新而不是添加Account
和Account.Profile
。
例如:
public async Task UpdateModel(Account model)
{
db.Accounts.Attach(model);
db.Entry(model).State = EntityState.Modified;
await db.SaveChangesAsync();
}
model
中的子配置文件將被視為新實體。
我怎樣才能更新子實體呢?
所以我的目的不是使用實體作為view model
。 我正在開發一個 object 映射器,其中 map 從 vm 到 model 的所有屬性,反之亦然。
像這樣的東西:
vm.MapTo<Model>(ref existing);
問題是 EF 總是將從view model
映射的子實體視為新實體。
這是我的映射 function
public void MapTo<T>(ref T instance)
{
var fromProperties = this.GetType().GetProperties();
var toProperties = typeof(T).GetProperties();
foreach (PropertyInfo prop in fromProperties)
{
string propName = prop.Name;
if (prop.CustomAttributes.Count() > 0)
{
MapToAttribute mapAttribute = (MapToAttribute)Attribute.GetCustomAttribute(prop, typeof(MapToAttribute));
AutoGeneratedAttribute autoGeneratedAttribute = (AutoGeneratedAttribute)Attribute.GetCustomAttribute(prop, typeof(AutoGeneratedAttribute));
if (mapAttribute != null)
propName = mapAttribute.MappedProperty;
if (autoGeneratedAttribute != null)
propName = "";
}
PropertyInfo mappedProp = toProperties.Where(m => m.Name == propName).FirstOrDefault();
if (mappedProp != null)
{
object value = prop.GetValue(this);
if (value != null && value.GetType() == typeof(DateTime))
{
DateTime dateValue = ((DateTime)(value)).ToUniversalTime();
mappedProp.SetValue(instance, dateValue);
}
else if (value != null && value.GetType() == typeof(DateTime?))
{
DateTime? dateValue = ((DateTime?)(value)).Value.ToUniversalTime();
mappedProp.SetValue(instance, dateValue);
}
else
{
mappedProp.SetValue(instance, value);
}
}
}
}
從 UI 接受 model 時要小心。 這不是一個好習慣。 通過這種方式,您可以選擇存儲的內容,也可以對其進行驗證。
再次從 db 查詢項目
public async Task UpdateModel(Account model)
{
var dbItem = await db.Accounts.Include(x=>x.Profile).FirstOrDefaultAsync(m => m.ID == model.Id);
//map values from model to dbItem
await db.SaveChangesAsync();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.