在Entity Framework中的LINQ查询中使用AsNoTracking
方法时,是否应该针对每个表或整个查询使用它以禁用整个查询的更改跟踪?
1。针对整个查询
var query = (from t1 in db.Table1
from t2 in db.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1).AsNoTracking()
2。针对每个表格
var query = (from t1 in db.Table1.AsNoTracking()
from t2 in db.Table2.AsNoTracking().Where(o => t1.ConditionId == o.ConditionId)
select t1)
我的目的是禁用整个查询的更改跟踪,但如果不需要,则不希望对每个表使用它。
MSDN引用此方法的文档中的查询对象:
此方法通过调用底层的AsNoTracking方法来工作 查询对象。如果基础查询对象没有 AsNoTracking方法,然后调用此方法将不执行任何操作。
答案 0 :(得分:37)
基于测试我刚刚做出两个结果是一样的。使用Table Level或QueryLevel AsNoTracking导致没有实体被保留到ChangeTracker中。但不管怎样,Table2中的实体永远不会放在ChangeTracker中,正如你在WithtoutAsNoTracking测试中看到的那样。
基于这个假设,您确实在查询t1和t2中的数据。当我查询所有条目仍然添加到查询中的单个AsNoTracking时,我添加了一个测试,没有跟踪任何条目。如果将AsNoTracking()直接放在table1上,则不会跟踪table1和table2中的实体。
[TestMethod]
public void QueryLevelAsNoTracking()
{
using (var context = new DbContext())
{
var query = (from t1 in context.Table1
from t2 in context.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1).AsNoTracking();
var list = query.ToList();
Assert.AreEqual(0, context.ChangeTracker.Entries().Count());
}
}
[TestMethod]
public void TableLevelAsNoTracking()
{
using (var context = new DbContext())
{
var query = (from t1 in context.Table1.AsNoTracking()
from t2 in context.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1);
var list = query.ToList();
Assert.AreEqual(0, context.ChangeTracker.Entries().Count());
}
}
[TestMethod]
public void WithtoutAsNoTracking()
{
using (var context = new DbContext())
{
var query = (from t1 in context.Table1
from t2 in context.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1);
var list = query.ToList();
Assert.AreEqual(7, context.ChangeTracker.Entries().Count(x => x.Entity is Table1));
Assert.AreEqual(0, context.ChangeTracker.Entries().Count(x => x.Entity is Table2));
}
}
[TestMethod]
public void QueryLevelAsNoTracking_SelectAllData()
{
using (var context = new DbContext())
{
var query = (from t1 in context.Table1
from t2 in context.Table2.Where(o => t1.ConditionId == o.ConditionId)
select new
{
t1,
t2
}).AsNoTracking();
var list = query.ToList();
Assert.AreEqual(0, context.ChangeTracker.Entries().Count());
}
}
[TestMethod]
public void Table1AsNoTracking_SelectAllData()
{
using (var context = new DbContext())
{
var query = (from t1 in context.Table1.AsNoTracking()
from t2 in context.Table2.Where(o => t1.ConditionId == o.ConditionId)
select new
{
t1,
t2
});
var list = query.ToList();
Assert.AreEqual(0, context.ChangeTracker.Entries().Count(x => x.Entity is Table1));
Assert.AreEqual(0, context.ChangeTracker.Entries().Count(x => x.Entity is Table2));
}
}
另外,我在join子句中删除了AsNoTracking From Table2,因为它导致了异常。
System.ArgumentException:方法'System.Data.Entity.Infrastructure.DbQuery
1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery
1 [DataModel.Table2]'无法使用类型'System.Data.Objects.ObjectQuery`1 [DataModel]的实例调用。表2]'