实体框架中LINQ查询中的AsNoTracking的范围

Nic*_*ick 27 entity-framework

AsNoTracking在Entity Framework中的LINQ查询中使用该方法时,是否应该针对每个表或整个查询使用该方法以禁用整个查询的更改跟踪?

1.反对整个查询

var query = (from t1 in db.Table1
            from t2 in db.Table2.Where(o => t1.ConditionId == o.ConditionId)
            select t1).AsNoTracking()
Run Code Online (Sandbox Code Playgroud)

2.对着每张桌子

var query = (from t1 in db.Table1.AsNoTracking()
            from t2 in db.Table2.AsNoTracking().Where(o => t1.ConditionId == o.ConditionId)
            select t1)
Run Code Online (Sandbox Code Playgroud)

我的目的是禁用整个查询的更改跟踪,但如果不需要,则不希望对每个表使用它.

MSDN引用此方法的文档中的查询对象:

此方法通过调用基础查询对象的AsNoTracking方法来工作.如果基础查询对象没有AsNoTracking方法,则调用此方法将不执行任何操作.

Ale*_*eau 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));
        }
    }
Run Code Online (Sandbox Code Playgroud)

另外,我从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]'的实例调用

  • 这是一个全面的答案.谢谢. (4认同)