Подтвердить что ты не робот

Объем AsNoTracking в запросе LINQ в Entity Framework

При использовании метода AsNoTracking в запросе LINQ в Entity Framework, следует ли использовать его для каждой таблицы или запроса в целом, чтобы отключить отслеживание изменений для всего запроса?

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, тогда вызов этого метода ничего не сделает.

4b9b3361

Ответ 1

На основании теста я только что сделал оба результата одинаковыми. использование уровня таблицы или QueryLevel AsNoTracking приводит к тому, что никакие объекты не удерживаются в tine ChangeTracker. Но в любом случае объекты из таблицы 2 никогда не помещаются внутри ChangeTracker, как вы можете видеть в тесте WithtoutAsNoTracking.

Основываясь на предположении, что вы действительно запрашиваете данные из t1 и t2. Я добавил тест, когда я запрашиваю, что все записи по-прежнему содержат одно добавление AsNoTracking, никаких записей не отслеживается. Тем не менее, если вы помещаете AsNoTracking() непосредственно в таблицу1, объекты из таблицы 1 и из таблицы2 не отслеживаются.

    [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 внутри предложения join, потому что он вызывает исключение.

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]