所以我是 EF 的新手(我正在使用 EF6)并且我在理解这个概念时遇到问题,我正在尝试使用子集合更新实体。
这是我的实体类:
public class TimeSheet
{
public int TimeSheetID { get; set; }
public virtual ICollection<TimeSheetDetail> Details { get; set; }
}
public class TimeSheetDetail
{
public int TimeSheetDetailID { get; set; }
public int TimeSheetID { get; set; }
public virtual TimeSheet TimeSheet { get; set; }
}
我的更新方法:
public void Update(TimeSheet obj)
{
var objFromDB = Get(obj.TimeSheetID);
var deletedDetails = objFromDB.Details.Except(obj.Details).ToList();
_dbContext.Entry(obj).State = EntityState.Modified;
//track if details exist
foreach (var details in obj.Details)
{
_dbContext.Entry(details).State = details.TimeSheetDetailID == 0 ? EntityState.Added : EntityState.Modified;
}
//track deleted item
foreach (var deleted in deletedDetails)
{
_dbContext.Entry(deleted).State = EntityState.Deleted;
}
}
public TimeSheet Get(object id)
{
//return _timeSheet.Find(id); //Without AsNoTracking I got error
int x = Convert.ToInt32(id);
return _timeSheet.AsNoTracking().SingleOrDefault(a => a.TimeSheetID == x);
}
上面的代码给我附加一个'ClassName'类型的实体失败,因为另一个相同类型的实体已经有相同的主键值
。所以我的问题是:
如何使用 EF 更新子集合?意味着我需要添加新的,如果它不存在于数据库中,否则更新,或者如果它在
POST
中被删除,则从数据库中删除。如果我不使用
AsNoTracking()
,它将抛出Saving or accepting changes failed because multiple than one entity of type 'ClassName' have the same primary key value
。我注意到错误是由于我的DbSet
如果我不使用AsNoTracking()
将数据库中的数据添加到其Local
属性引起的导致 EF 框架抛出错误,因为它认为我有重复数据。这实际上是如何工作的?如您所见,我正在尝试将
objFromDb
与obj
进行比较,以检查用户是否删除了其中一个详细信息,以便我可以将其从数据库中删除.相反,我从收集结果中得到了一堆DynamicProxies
。什么是DynamicProxies
,它是如何工作的?EF有什么好的文章或者101教程吗?到目前为止,我只看到一个简单的方法,它对我的情况没有帮助,我环顾四周,找到了一个混合的答案如何做事。老实说,在这一点上,我希望我只使用经典的 ADO.Net 而不是 EF。
最佳答案
为了更好地理解 Entity Framework ,请将 DbContext
视为您的应用程序和数据库之间的代理。
DbContext
将缓存所有内容并将使用缓存值中的每一位数据,除非您告诉它不要这样做。
对于 1.:这取决于您的环境,如果您的 DbContext
未在选择和更新实体之间进行处理,您只需调用 SaveChanges
并且您的数据将被保存。如果您的 DbContext
被处置,您可以从上下文中分离实体,更改数据,重新附加它们并将 EntityState
设置为已修改。
我不能给你 100% 肯定的答案,因为我大约半年前就停止使用 Entity Framework 了。但我知道更新复杂的关系是一件痛苦的事情。
对于 2.:AsNoTracking
命令告诉 EF 不要跟踪对该查询中的实体所做的更改。例如,您从数据库中选择 5 个时间表,更改第一个实体中的一些值并删除最后一个实体。 DbContext
知道第一个实体被更改而最后一个实体被删除,如果您调用 SaveChanges
DbContext
将自动更新第一个实体,删除最后一个并保持其他不变。现在您尝试自己更新实体并将第一个实体再次附加到 DbContext。
DbContext 现在将有两个具有相同键的实体,这会导致您出现异常。
对于3.:DynamicProxies
是 Entity Framework 用来跟踪这些实体变化的对象。
对于 4.:检查此 link ,还有一本关于 Entity Framework 6的好书(书名:《Programming Entity Framework》)
关于c# - 对 EF 中的跟踪感到困惑(使用子集合更新实体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32964990/