C# 实体框架AddorUpdateOrdOnToWn与嵌套
我首先将EF代码用于以下模型:C# 实体框架AddorUpdateOrdOnToWn与嵌套,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我首先将EF代码用于以下模型: public class Root { public ChildA A { get; set; } public ChildB B { get; set; } public ChildC C { get; set; } } 假设你有一个控制器 public class RecordController { ... public void Save(Root root) { ... }
public class Root
{
public ChildA A { get; set; }
public ChildB B { get; set; }
public ChildC C { get; set; }
}
假设你有一个控制器
public class RecordController
{
...
public void Save(Root root)
{
...
}
...
}
并且您的Root
控制器已从客户端接收到一个模型,该模型包含以下更改:属性a
是全新的,尚未添加到数据库中,需要创建;属性B
已存在于数据库中,需要更新;属性C
未更改
操作
Save
不知道属性更改是什么,它只需要正确更新记录
,并创建缺少的或更新现有的子模型,也可能一些子类也有自己的嵌套更改,因此,我需要一个方法,该方法将以某种方式通过模型递归,将新模型与现有模型进行比较,并应用适当的更改。那么我该怎么做呢?我最终将我的每个模型和ViewModel类与EntityState
属性连接起来,所以现在当我更改某些属性时,我将EntityState
设置为changed
状态,当我创建一个属性时,我将属性设置为stateAdded
,最初,模型以未更改的状态初始化,基本上如下所示:
[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
}
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;
}
}
}
public void AttachAndMarkAs(T entity,EntityState,Func id),其中T:class
{
var分录=分录(实体);
if(entry.State==EntityState.Detached)
{
var set=set();
T attachedEntity=set.Find(id(实体));
如果(附件身份!=null)
{
var attachedEntry=条目(attachedEntity);
attachedEntry.CurrentValues.SetValues(实体);
}
其他的
{
entry.State=状态;
}
}
}
+1表示方法名称。在EF中提交对象图(仍然)是一项乏味的工作。在Lerman&Miller的书DbContext中,提出了一种使用手动编码的自跟踪实体(种类)的方法。目前还不是银弹。它可能很有用:
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);
}
}
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;
}
}
}