为什么在Entity Framework 6中使用Attach来更新数据?

22

在寻找通过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() 呢?就我所理解的来说,该记录并没有以任何方式附加到上下文中。我已阅读这本书这个教程中相关的章节,但它们都使用了两个查询的方法。我也在 Stack Overflow 上搜索过,但没有找到答案。请帮我解释一下或提供其他好的材料,谢谢。
1个回答

43
如果您已经知道数据库中存在的实体,但当前上下文没有跟踪它(这在您的情况下是正确的),则可以使用DbSet上的Attach方法告诉上下文跟踪该实体。因此,总结一下Attach方法的作用是在上下文中跟踪实体并将其状态更改为Unchanged。在此之后修改属性时,跟踪更改将为您更改其状态为Modified
在您提出的情况中,您明确告诉状态为Modified,同时将实体附加到上下文中。您可以在这篇文章中找到详细说明。 什么时候应该使用Attach方法? 当您知道数据库中已经存在实体但想要进行一些更改时。
var entity= new Entity{id=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(); 

何时应明确将实体状态更改为已修改?

当您拥有一个已知存在于数据库中但更改已经完成的实体时。这与您示例中的情况相同。


谢谢,但为什么这条记录目前被上下文跟踪? - Vitalii Isaenko
如果实体当前正在被跟踪,并且您更改了某些属性,则由于跟踪更改,实体的状态应更改为“Modified”,但是为此,您的实体应满足此要求 - ocuenca
我之前读过这一章,但可能真的误解了一些东西,问题仍然存在。如果我遵循要求,所有实体都会自动跟踪吗?我的例子表明,新添加的对象已经在某种程度上被上下文跟踪,那么为什么我要使用Attach()呢?而且为什么这个新对象被跟踪呢?谢谢您的解释,也许我深入挖掘了太多。 - Vitalii Isaenko
2
@VitaliiIsaenko 为什么这个新对象被跟踪?因为当您调用 ctx.Entry(record) 时,DbContext 将自动查找或创建实体并将其附加到上下文。 - Vyrira
2
没错,在那种情况下你不需要使用 Attach 方法。 - ocuenca
保存一个类对象列表,我们能否不附加它来完成? - Sujay Ghosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接