При использовании метода AsNoTracking
в запросе LINQ в Entity Framework следует ли его использовать для каждой таблицы или запроса в целом, чтобы отключить отслеживание изменений для всего запроса?
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, то вызов этого метода ничего не даст.
На основании только что проведенного теста оба результата одинаковы. использование уровня таблицы или QueryLevel AsNoTracking не приводит к удержанию сущностей в ChangeTracker. Но в любом случае сущности из Таблицы 2 никогда не помещаются внутрь 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));
}
}
Кроме того, я удалил 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.Table2]'