实体框架内LINQ查询中AsNoTracking的范围 [英] Scope of AsNoTracking within LINQ query in Entity Framework

查看:1157
本文介绍了实体框架内LINQ查询中AsNoTracking的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当在实体框架中使用LINQ查询中的 AsNoTracking 方法时,应该对每个表或整个查询进行使用,以禁用更改跟踪整个查询?

When utilising the AsNoTracking method within a LINQ query in Entity Framework, should it be used against each table or the query as a whole in order to disable change tracking for the entire query?

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)

我的目的是禁用整个查询的更改跟踪,但是如果不需要,则不想将其用于每个表。

My intention is to disable change tracking for the entire query but don't want to use it against each table if it isn't required.

MSDN 是指一个查询对象此方法的文档:

MSDN refers to a query object in the documentation for this method:


此方法通过调用底层
查询对象的AsNoTracking方法工作。如果基础查询对象没有
AsNoTracking方法,那么调用此方法将不会执行任何操作。

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中。但是无论哪种方式,表2中的实体都不会放在ChangeTracker中,如在WithtoutAsNoTracking测试中所看到的那样。

Based on a test I've just made both results are the same. using Table Level or QueryLevel AsNoTracking result in no entities being hold into tine ChangeTracker. But either way, entities from Table2 are never put inside of the ChangeTracker, as you can see in the WithtoutAsNoTracking test.

基于这个假设,你确实在查询数据从t1和t2。当我查询所有条目时,我添加了一个测试,仍然添加了一个AsNoTracking添加到查询中,没有条目被跟踪。如果您将AsNoTracking()直接放在table1上,则不会跟踪table1和table2中的实体。

Base on the assumption, that you are indeed querying data from t1 and t2. I've added a test when I'm querying all entries are still with a single AsNoTracking added to the query, no entry is tracked. Still if you put the AsNoTracking() directly on table1, the entities from table1 and from table2 aren't tracked.

    [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));
        }
    }

另外,我从表2中删除了AsNoTracking的连接子句,因为它引起了异常。

Also, I've remove the AsNoTracking From Table2 inside of the join clause because it was causing an exception.


System.ArgumentException:方法'System.Data.Entity.Infrastructure.DbQuery 1 [DataModel.Table12 AsNoTracking )'在类型'System.Data.Entity.Infrastructure.DbQuery 1 [DataModel.Table2]'上声明不能使用System.Data.Objects.ObjectQuery类型的实例调用[DataModel.Table2 ]'

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]'

这篇关于实体框架内LINQ查询中AsNoTracking的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆