35

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 メソッドがない場合、このメソッドを呼び出しても何も起こりません。

4

2 に答える 2

46

私が行ったばかりのテストに基づいて、両方の結果は同じです。Table Level または 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));
        }
    }

また、例外が発生していたため、join 句内の AsNoTracking From Table2 を削除しました。

System.ArgumentException: メソッド 'System.Data.Entity.Infrastructure.DbQuery 1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery1[DataModel.Table2]' は、タイプ 'System.Data.Objects.ObjectQuery`1[DataModel.Table2]' のインスタンスで呼び出すことはできません

于 2013-08-14T12:38:11.927 に答える