我是一名新手,对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);
}
以上代码给出了Attaching an entity of type 'ClassName' failed because another entity of the same type already has the same primary key value
。所以我的问题是:
如何使用EF更新子集合?即如果在
POST
中不存在于数据库中,则需要添加新的,否则进行更新,或者如果它已从POST
中删除,则从数据库中删除。如果我不使用
AsNoTracking()
,它会抛出Saving or accepting changes failed because more than one entity of type 'ClassName' have the same primary key value
。我注意到错误是由于我的DbSet
将数据从数据库添加到其Local
属性中引起的,如果我不使用AsNoTracking()
,这会导致EF框架抛出错误,因为它认为我有重复数据。这实际上是如何工作的?正如您所看到的,我正在尝试将
objFromDb
与obj
进行比较,以检查用户是否删除了其中一个详细信息,以便我可以将其从数据库中删除。相反,我从集合结果中得到了一堆DynamicProxies
。什么是DynamicProxies
,它是如何工作的?有关EF的任何好文章或101教程吗?到目前为止,我只看到了一个简单的教程,对我的情况没有帮助,我已经四处寻找,并找到了关于如何处理的混合答案。说实话,在这一点上,我希望我只是使用经典的ADO.Net而不是EF。