entity-framework - Entity Framework 中LINQ查询中AsNoTracking的范围

标签 entity-framework

在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在文档中引用此方法的查询对象:

This method works by calling the AsNoTracking method of the underlying query object. If the underlying query object does not have a AsNoTracking method, then calling this method will do nothing.

最佳答案

根据测试,我刚刚得出的结果是相同的。使用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));
        }
    }

另外,我已经从join子句中的Table2中删除了AsNoTracking,因为它引起了异常。

System.ArgumentException: Method 'System.Data.Entity.Infrastructure.DbQuery1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery1[DataModel.Table2]' cannot be called with instance of type 'System.Data.Objects.ObjectQuery`1[DataModel.Table2]'

关于entity-framework - Entity Framework 中LINQ查询中AsNoTracking的范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18231039/

相关文章:

entity-framework - EF Core,从netcore2.2更新到netcore3.1后出现无效列名异常

c# - EF 为关系创建了两个重复的 FK

c# - 不支持异常 : LINQ to Entities does not recognize the method

entity-framework - VS2012 的数据源工具箱不显示我的实体模型

c# - 基于字段列表和 Asc/Desc 规则的 OrderBy

entity-framework - EF Code First 给出错误:当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'People' 中插入标识列的显式值。

entity-framework - 如何从外部安逸的服务中填充电灯开关屏幕?

c# - 服务器错误 "Method not found: ' 无效 System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior( bool 值 )'."

c# - 使用 Entity Framework 在 sql server 中加密/解密列

c# - Multi-Tenancy - 为每个租户动态创建数据库