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 메서드가 없으면이 메서드를 호출하면 아무 것도 수행되지 않습니다.
테스트를 토대로 두 결과를 동일하게 만들었습니다. 테이블 레벨 또는 QueryLevel 사용 AsNoTracking은 엔티티가 없기 때문에 ChangeTracker를 유지합니다. 그러나 WithtoutAsNoTracking 테스트에서 볼 수 있듯이 Table2의 엔티티는 절대로 ChangeTracker 안에 들어 가지 않습니다.
기본 가정, 당신은 실제로 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 : Method 'System.Data.Entity.Infrastructure.DbQuery
1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery
[DataModel.Table2]'11[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery
호출 할 수 없습니다. 'System.Data.Objects.ObjectQuery`1 [DataModel.Table2]'을 입력하십시오.