为啥要使用 Attach 来更新 Entity Framework 6?

Posted

技术标签:

【中文标题】为啥要使用 Attach 来更新 Entity Framework 6?【英文标题】:Why use Attach for update Entity Framework 6?为什么要使用 Attach 来更新 Entity Framework 6? 【发布时间】:2017-04-22 20:40:32 【问题描述】:

在寻找通过 EF 执行 CRUD 操作的最佳实践时,我注意到强烈建议在更新实体之前使用 Attach()Find() 方法。它运行良好,根据 EF 文档,这些方法将实体获取到对我来说非常清楚的上下文。但是下面的代码让我很困惑

public void Update(object entity)

    Record record = new Record() 
        id = 1,
        value = 5
    ;
    using (SomeContext ctx = new SomeContext())
    
        ctx.Entry(record).State = EntityState.Modified;
        ctx.SaveChanges();
    

假设我们在数据库中有一条 id = 1 的记录。在这种情况下,上面的代码将更新记录(将值设置为 5)。问题是它为什么有效?那我为什么要使用Attach()?。据我了解,该记录并未以任何方式附加到上下文中。我阅读了this book 和the tutorial 的相关章节,但他们使用2-query-approach。我也上网了,但没有找到我的问题的答案。请帮我解释或一些好的数学。

【问题讨论】:

【参考方案1】:

如果您有一个您知道数据库中已经存在但当前未被上下文跟踪的实体(在您的情况下是这样),那么您可以使用 Attach 方法告诉上下文跟踪该实体在DbSet。 所以总而言之,Attach 方法所做的就是跟踪上下文中的实体并将其状态更改为 Unchanged。当您在此之后修改属性时,跟踪更改会将其状态更改为 Modified。 在您在上面公开的情况下,您明确地告诉状态是 Modified 但也将实体附加到您的上下文中。你可以在这个post找到详细的解释。

什么时候应该使用Attach 方法?

当您知道某个实体已存在于数据库中但想要进行一些更改时:

var entity= new Entityid=1;
context.YourDbSet.Attach(entity); 

// Do some change...  
entity.value=5;

context.SaveChanges(); 

这是一样的:

 context.Entry(entity).State = EntityState.Unchanged; 

// Do some change... 
entity.value=5; 

context.SaveChanges(); 

何时应将实体的状态显式更改为已修改?

当您有一个您知道数据库中已经存在的实体但已经进行了更改时。您的示例的相同场景

【讨论】:

谢谢,但为什么当前上下文会跟踪此记录? 如果实体当前被跟踪并且您更改了某些属性,则由于跟踪更改,实体的状态应更改为Modified,但为此您的实体应符合此requirements 我之前读过这一章,可能真的误解了一些东西,但问题仍然存在。如果我遵循要求,是否会自动跟踪所有实体?我的示例显示新添加的对象已经被上下文以某种方式跟踪,那么我为什么要使用Attach()?为什么要跟踪这个新对象?谢谢你的解释,也许我挖得太深了。 @VitaliiIsaenko 为什么要跟踪新对象?因为当您调用ctx.Entry(record) 时,DbContext 会自动查找或创建您的实体并将其附加到上下文中。 没错,在那种情况下,您不需要使用Attach 方法。

以上是关于为啥要使用 Attach 来更新 Entity Framework 6?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 数据部分更新之Attach/Detach(转)

为啥我不能用 Attach() 更新 IdentityUser?

直接使用提交过来的类来更新字段EntityState.Modified并过滤null值的方法

为啥在我运行迁移时 Entity Framework 包会自动更新?

使用 MySQL 时,为啥 Entity Framework 4 试图将 long 转换为小数?

EF部分字段更新,忽略为null字段