C# 在使用DbContext进行更新之前,首先查找项以计算更改是否是一种好做法?

C# 在使用DbContext进行更新之前,首先查找项以计算更改是否是一种好做法?,c#,entity-framework,service-layer,change-tracking,loose-coupling,C#,Entity Framework,Service Layer,Change Tracking,Loose Coupling,首先,我讨论的是松耦合场景,在这个场景中,我们不直接在客户端使用DbContext,而是在服务层中使用。 因此DbContext无法帮助跟踪更改以正常更新操作。事实上,我们可以在项目中直接使用DbContext,但我感觉它与实体框架的耦合相当紧密。我总是喜欢创建一个单独的服务层(即使该项目是一个非常适合直接使用DbContext的Windows桌面应用程序) 因此,在这种松耦合场景中,我们需要自己检测更改,而不需要DbContext的帮助。这里有几个选项,其中一个(我在这里问)是检测来自旧实例和

首先,我讨论的是松耦合场景,在这个场景中,我们不直接在客户端使用DbContext,而是在服务层中使用。 因此DbContext无法帮助跟踪更改以正常更新操作。事实上,我们可以在项目中直接使用DbContext,但我感觉它与实体框架的耦合相当紧密。我总是喜欢创建一个单独的服务层(即使该项目是一个非常适合直接使用DbContext的Windows桌面应用程序)

因此,在这种松耦合场景中,我们需要自己检测更改,而不需要DbContext的帮助。这里有几个选项,其中一个(我在这里问)是检测来自旧实例和新实例的更改。在这里,可以从数据库中请求(查询)旧实例,如下所示:

public void UpdateItem(Item item){
   using(var db = new SomeDbContext()){
        var oldItem = db.Set<Item>().Find(item.SomeKey);
        db.Set<Item>().Attach(item);
        //this will actually update some EntityState for the item's properties 
        detectChanges(oldItem, item);
        db.SaveChanges();
   }
}
public void UpdateItem(项目){
使用(var db=new SomeDbContext()){
var oldItem=db.Set().Find(item.SomeKey);
db.Set().Attach(项目);
//这实际上会更新项目属性的某些EntityState
检测变更(旧项、旧项);
db.SaveChanges();
}
}
上述方法的代价是,需要再查询一次才能找到旧项。此外,如果新的
项目
实际部分加载(例如仅加载项目的某些属性,因为只有那些属性对某些特定视图感兴趣),则这可能是危险的,在这种情况下,
detectChanges
可能会错误更新项目的属性“
EntityState
,这反过来会意外地清除某些缺失属性的值


所以我在这一点上有点犹豫。真的,如果你有更好的方法来保存/更新这个场景中的项目,请与我分享。谢谢你的帮助

> P>您应该考虑使用行版本(时间戳)来处理非预期的更新。p>
在这一点上,您不需要检测更改。只需附加并保存更改。如果要保存的对象已过时,EF将抛出一个并发异常,您可以通过通知用户、尝试合并或失败来处理该异常。这取决于你。

你到底想做什么?在点击
SaveChanges()
之前,是否要确定
项的属性值是否与
旧项的值不同?
detectChanges()
内部发生了什么?@WahidMasud如果您真的使用过实体框架,您应该了解
detectChanges
内部应该是什么。附加后,该实体被视为未更改。
detectChanges
将其属性状态设置为modified。但是要设置哪些属性呢?这需要新旧项的实例。如果项仅部分加载(并且您不知道已设置了哪些属性),则无法找出哪些属性为null,因为您有意将它们设置为该值,而哪些属性为null,因为它们根本没有加载。我会记录哪些属性已经加载或切换到连接的条目。你肯定不明白我的问题是什么。这里的场景是松散耦合的,因此即使在保存更改之前,我们也需要在实体实例上实际标记更改。通过在紧耦合场景中的自动观察,这是EF自己自动完成的,但在松耦合场景中,它无能为力。行版本帮助您检测是否有其他用户更新/更改了数据库中的相应数据。如果没有任何冲突,您仍然必须在不知道任何更改的情况下更新数据,那么EF如何更新您的数据?