【发布时间】:2020-06-20 14:58:05
【问题描述】:
Entity Framework Core 中 AsNoTracking() 的文档说,在保存数据库上下文时,对它的任何编辑都不会被持久化。 我注意到使用 AsNoTracking() 时的另一个区别,即如果数据库上下文有未保存的编辑并且您使用 AsNoTracking() 查询它,则不会返回这些更改。 该文档听起来好像只有对 AsNoTracking() 查询所做的编辑不会在保存时被跟踪和持久化,但似乎返回的内容也会有所不同。
如果这确实是预期的行为,我不确定最佳设计模式。 我在所有只读查询中都使用了 AsNoTracking(),但这意味着我有一个错误,因为我的设计是这样的:
修改数据的控制器端点:
- 在服务中调用某些可能会或可能不会改变数据库的东西
- 调用服务中的其他内容,使用 AsNoTracking() 进行只读查询
- 控制器保存数据库上下文
其目的是任何控制器端点都可以调用任意数量的服务方法,这些服务方法可能会或可能不会改变数据库,数据库上下文是限定范围的,因此它们在调用之间共享,最终控制器会持久保存更改。 问题是上面的#2 不会返回在#1 中完成的更改。这应该如何解决?这些服务可以调用其他服务,这些服务可能会从已经修改过的地方获取一些数据,所以我不能只是到处传递模型。 我应该从任何地方删除 AsNoTracking() 并收工吗?或者我应该在每次写入后添加一个保存调用?或者还有什么我可以做的吗?
TLDR:我希望在只读查询中使用 AsNoTracking() 以提高速度,但它不会返回任何未保存的更改。我应该删除 AsNoTracking(),每次编辑后保存,还是有更好的方法?
编辑: 这是我的意思的sn-p;任何带有 AsNoTracking() 的查询都会忽略在保存之前对上下文所做的任何编辑,这让我想知道 AsNoTracking() 到底有什么用处:
var userSessionEntry = await this.mainContext.Sessions
.Where(t => t.AccountId == session.AccountId).FirstAsync();
userSessionEntry.AccountId = Guid.Empty;
var userSessionEntry2 = await this.mainContext.Sessions
.Where(t => t.AccountId == session.AccountId).AsNoTracking().FirstAsync();
Console.WriteLine(userSessionEntry2.AccountId); // prints original AccountId and not an empty id
编辑 2: 我正在使用 Entity Framework Core 的最新预览版; 5.0.0-preview.5.20278.
谢谢。
【问题讨论】:
-
请edit您的问题包含您拥有的源代码,该代码显示您如何使用
AsNoTracking()读取数据,您如何在上下文中未保存的更改,您如何尝试从上下文以及您如何知道数据不正确。如何提供代码请见minimal reproducible example。 -
嗨@Progman,感谢您的回复。我不确定你的意思是什么,例如“你怎么知道数据不正确”?你在帖子中挑战这个主张吗?我添加了“证明”,即在保存更改之前,在后续查询中使用 AsNoTracking() 不会将修改后的条目返回到问题中。我没有代码问题所以无法提供样品,这是设计问题。
-
你有哪个版本的EF核心?
-
嗨@GuruStron!我正在使用最新的预览版 5.0.0-preview.5.20278。
标签: c# asp.net-core entity-framework-core