EF核心6和.NET 6。
假设我的所有实体都有一个LastUpdateAt属性,它是一个DateTime,每次添加或修改实体时都会更新该属性。
我从上下文中获得一个实体,并将其显示给用户(网页、WPF窗口等)。在某个时候,用户单击Save按钮。
在保存之前,我想检查实体是否已经被其他人更新了,因为我得到了我的副本。然而,我正在努力寻找如何做到这一点。
如果我查询上下文,它只会返回我已经拥有的实体(包括我的用户所做的任何更改)。
如果刷新该实体,它将覆盖上下文中的实体,从而丢失用户的更改。
如何检查数据库版本是否具有比上下文中的时间戳更新的时间戳?
谢谢
发布于 2022-02-09 23:07:08
将讨论移到这里,因为我需要粘贴更长的文本。在这篇文章中,据说在SaveChanges()期间,如果数据库版本在同时被修改,它将抛出DbUpdateConcurrencyException。在该异常中,您拥有所有3个值,并且可以决定如何解决冲突:
解决并发冲突涉及将当前DbContext中的挂起的更改与数据库中的值合并。合并的值将根据应用程序的不同而有所不同,并且可能由用户输入指导。
有三组值可用于帮助解决并发冲突:
当前值是应用程序试图写入数据库的值。原始值是最初从数据库中检索的值,然后再进行任何编辑。数据库值是当前存储在数据库中的值。
发布于 2022-02-09 23:10:11
如果您正在加载一个实体,保持一个DbContext实例处于打开状态,更新该实体,然后保存到同一个DbContext实例,那么默认情况下,您依赖EF来管理并发性。这是在“最后的胜利”之后。您可以让EF通过在[ConcurrencyCheck]属性上添加LastUpdateAt或通过[Timestamp]使用行版本来管理并发性。如果基础数据已被更新,这将导致EF更新失败。从那以后,你必须决定如何处理它。
如果您想自己执行并发性检查,那么有几个选项。
ProjectTo获取视图模型,然后使用Map(source, destination)复制值。以这种方式加载数据(包括上次修改的at value ),进行更改,然后在保存时加载数据,验证修改后的at等,然后跨域复制值并保存。DbContext实例进行范围检查。。
private DateTime getFooLastUpdateAt(int fooId)
{
using(var context = new AppDbContext())
{
var lastUpdateAt = context.Foos
.Where(x => x.FooId == fooId)
.Select(x => x.LastUpdateAt)
.Single();
return lastUpdateAt;
}
}这可以使用注入的DbContext工厂或类似的方法来创建DbContext实例。
https://stackoverflow.com/questions/71057616
复制相似问题