c# - 对 EF 中的跟踪感到困惑(使用子集合更新实体)

标签 c# entity-framework entity-framework-6

所以我是 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'类型的实体失败,因为另一个相同类型的实体已经有相同的主键值。所以我的问题是:

  1. 如何使用 EF 更新子集合?意味着我需要添加新的,如果它不存在于数据库中,否则更新,或者如果它在 POST 中被删除,则从数据库中删除。

  2. 如果我不使用 AsNoTracking(),它将抛出 Saving or accepting changes failed because multiple than one entity of type 'ClassName' have the same primary key value 。我注意到错误是由于我的 DbSet 如果我不使用 AsNoTracking() 将数据库中的数据添加到其 Local 属性引起的导致 EF 框架抛出错误,因为它认为我有重复数据。这实际上是如何工作的?

  3. 如您所见,我正在尝试将 objFromDbobj 进行比较,以检查用户是否删除了其中一个详细信息,以便我可以将其从数据库中删除.相反,我从收集结果中得到了一堆 DynamicProxies 。什么是 DynamicProxies,它是如何工作的?

  4. 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/

相关文章:

c# - 如何检查正则表达式组是否相等?

c# - Entity Framework 尝试在添加条目时显式添加 ID

c# - 在将 .CSV 导入 SQL 数据库时将空字段设置为 null,而不是默认值

entity-framework - 使用 Entry<TEntity>().CurrentValues.SetValues() 不会更新集合

entity-framework - 如果我对已删除的实体调用 EF Reload 会怎样?

c# - Async PartialView 导致 "HttpServerUtility.Execute blocked..."异常

c# - 电子邮件中的 Unicode 字符不会引发异常

c# - 音频的捕获和播放 (WP8.1 XAML)

c# - asp net core 1 RC2 AccountController注入(inject)

c# - Entity Framework 6 延迟加载怪癖