2013-08-14 30 views
23

Entity FrameworkのLINQクエリ内でAsNoTrackingメソッドを使用する場合、クエリ全体の変更追跡を無効にするために、各テーブルまたはクエリ全体に対して使用する必要がありますか?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メソッドがない場合、このメソッドを呼び出すと何も行われません。

答えて

32

テストに基づいて、私は両方の結果を同じにしました。テーブルレベルまたはQueryLevel AsNoTrackingを使用すると、ChangeTrackerに保持されているエンティティがなくなります。しかし、どちらの方法でも、WithtoutAsNoTrackingテストで見られるように、Table2のエンティティはChangeTrackerの内部に置かれません。

実際には、t1とt2のデータを照会していると仮定します。私はすべてのエントリをクエリしているときにテストを追加しましたが、クエリに1つの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.Table2タイプのインスタンスで呼び出すことができません] '

+4

これは包括的な答えです。ありがとう。 – Nick

関連する問題