我首先在以下模型中使用 EF 代码:
public class Root
{
public ChildA A { get; set; }
public ChildB B { get; set; }
public ChildC C { get; set; }
}
假设你有一个 Controller
public class RecordController
{
...
public void Save(Root root)
{
...
}
...
}
并且您的 Root
Controller 已收到来自客户端的模型,其中包含以下更改:属性 A
是全新的,尚未添加到数据库中,需要添加已创建,属性 B
已存在于数据库中,需要更新,属性 C
未更改。
Action Save
并不知道属性变化是什么,它只需要适本地更新Record
并创建丢失的或更新现有的子模型,这也是可能的一些 Child
类也可能有自己的嵌套更改,因此我需要一种方法,该方法将以某种方式递归模型,将新模型与现有模型进行比较,并应用适当的更改。那我该怎么做呢?
最佳答案
我最终将我的每个模型和 ViewModel 类与 EntityState
属性连接起来,所以现在当我更改某些属性时,我将 EntityState
设置为 changed
状态,当我创建一个时,我将属性设置为状态 Added
,最初模型初始化为 Unchanged
状态,基本上它看起来像下面这样:
[Table("City")]
[KnownType(typeof(Country))]
public class City
{
public City()
{
Airports = new List<Airport>();
LastUpdate = DateTime.Now;
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int32 Id { get; set; }
public Int32? CountryId { get; set; }
[StringLength(50)]
public String Name { get; set; }
[Range(-12, 13)]
public Int32? TimeZone { get; set; }
public Boolean? SummerTime { get; set; }
public DateTime? LastUpdate { get; set; }
[ForeignKey("CountryId")]
public virtual Country Country { get; set; }
[NotMapped]
public EntityState? EntityState { get; set; } // <----------- Here it is
}
然后在服务器上我执行以下操作
[HttpPost, HttpGet]
public HttpResponseMessage SaveRecord(RecordViewModel record)
{
var model = Mapper.Map<Record>(record);
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
db.Attach(model);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
这是 Attach 方法的实现:
public void Attach(City entity)
{
if (entity != null)
{
Attach(entity.Country);
AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id);
}
}
public void Attach(Country entity)
{
if (entity != null)
{
AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id);
}
}
AttachAndMarkAs 具有以下实现:
public void AttachAndMarkAs<T>(T entity, EntityState state, Func<T, object> id) where T : class
{
var entry = Entry(entity);
if (entry.State == EntityState.Detached)
{
var set = Set<T>();
T attachedEntity = set.Find(id(entity));
if (attachedEntity != null)
{
var attachedEntry = Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
}
else
{
entry.State = state;
}
}
}
关于c# - 具有嵌套的 Entity Framework AddOrUpdateOrDontBother,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17254849/