c# - 可以使用 .ToList() 绕过 DbContext 跟踪吗?
问题描述
我想DbContext
尽可能缩短我的寿命,所以我利用了这个using
声明。
但是,由于实体框架跟踪实体,我不能做这样的事情:
public IEnumerable<Person> GetPersons()
{
using (var db = new AppContext())
{
Logging.Log(Information, "Requested getPersons from service");
return db.Persons;
}
}
因为只要我Persons
在 ViewModel 中使用列表,我就会收到一个 InvalidOperationException(在我使用对象之前上下文已经被释放)。
为了绕过它,我通过调用将查询结果转换为具体的列表ToList()
public IEnumerable<Person> GetPersons()
{
using (var db = new AppContext())
{
Logging.Log(Information, "Requested getPersons from service");
return db.Persons.ToList();
}
}
这是一件好事吗?AsNoTracking()
没有任何影响,因为如果上下文被释放,它仍然返回一些被丢弃的实体。
解决方案
如果您只是将db.Persons
其返回IEnumerable<Person>
给某个调用者,然后在该调用者可以迭代结果之前处理数据库上下文,您将得到异常,因为实体框架默认具有惰性。 ToList
通过在释放上下文之前立即强制迭代来解决这个问题,但仍然有对象跟踪的开销,因此结合ToList
使用AsNoTracking
可以获得最佳性能。
AsNoTracking
删除了数据库上下文中的一些内部跟踪代码,它不允许您IEnumerable<Person>
在处理上下文后传递出去,您仍然需要这样做ToList
。
使用扩展方法AsNoTracking
,然后调用ToList
:
db.Persons.AsNoTracking().ToList();
或者,您可以在 db 上下文的 change tracker 属性上禁用更改跟踪,以使整个内容只读,从而避免AsNoTracking
到处调用。你仍然需要ToList
这种方法。
/// <summary>
/// Disable all change tracking - place in db context sub class
/// </summary>
public void DisableChangeTracking()
{
ChangeTracker.AutoDetectChangesEnabled = false;
ChangeTracker.LazyLoadingEnabled = false;
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
推荐阅读
- macos - Python 虚拟环境,Py2app 构建,wxpython 错误
- c# - 某些要插入的对象重复时的 Web API 响应
- cordova - 构建科尔多瓦应用程序突然停止工作
- jquery - 如何在两个不同的表中使用 JQuery 更改 TH 的样式
- php - 如何在 SQL 中将列值与 sum 函数进行比较?
- javascript - 缩放后如何调整平移?
- angular - forkJoin 用于多个 NgRx Store 订阅
- c# - 使用 RayCast 到空游戏对象的附加脚本现在无法正常工作,为什么?
- java - 数据库的自动更新会在错误的一侧创建单向连接
- excel - Excel文件到字典