2013-08-14 35 views
23

Khi sử dụng phương thức AsNoTracking trong truy vấn LINQ trong Entity Framework, nên sử dụng nó trong mỗi bảng hoặc truy vấn để tắt theo dõi thay đổi cho toàn bộ truy vấn?Phạm vi của AsNoTracking trong truy vấn LINQ trong Entity Framework

1. Chống lại toàn bộ truy vấn

var query = (from t1 in db.Table1 
      from t2 in db.Table2.Where(o => t1.ConditionId == o.ConditionId) 
      select t1).AsNoTracking() 

2. Chống mỗi bảng

var query = (from t1 in db.Table1.AsNoTracking() 
      from t2 in db.Table2.AsNoTracking().Where(o => t1.ConditionId == o.ConditionId) 
      select t1) 

Ý định của tôi là để vô hiệu hóa theo dõi cho toàn bộ truy vấn thay đổi nhưng không muốn sử dụng nó trên mỗi bảng nếu nó không được yêu cầu.

MSDN đề cập đến một đối tượng truy vấn trong tài liệu hướng dẫn cho phương pháp này:

Phương pháp này hoạt động bằng cách gọi phương thức AsNoTracking của đối tượng truy vấn cơ bản. Nếu đối tượng truy vấn cơ bản không có phương thức AsNoTracking, thì việc gọi phương thức này sẽ không làm gì cả.

Trả lời

32

Dựa trên thử nghiệm tôi vừa tạo ra cả hai kết quả đều giống nhau. sử dụng Cấp độ Bảng hoặc QueryLevel AsNoTracking dẫn đến không có thực thể nào được giữ trong Trình theo dõi thay đổi của tine. Nhưng cả hai cách, các thực thể từ Bảng 2 không bao giờ được đặt bên trong ChangeTracker, như bạn có thể thấy trong bài kiểm tra WithtoutAsNoTracking.

Dựa trên giả định, bạn thực sự đang truy vấn dữ liệu từ t1 và t2. Tôi đã thêm một thử nghiệm khi tôi đang truy vấn tất cả các mục vẫn còn với một AsNoTracking đơn được thêm vào truy vấn, không có mục nào được theo dõi. Tuy nhiên, nếu bạn đặt AsNoTracking() trực tiếp trên bảng 1, các thực thể từ bảng 1 và từ bảng 2 không được theo dõi.

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

Ngoài ra, tôi đã xóa AsNoTracking From Table2 bên trong mệnh đề nối vì nó gây ra ngoại lệ.

System.ArgumentException: Phương pháp 'System.Data.Entity.Infrastructure.DbQuery 1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery 1 [DataModel.Table2]' không thể được gọi với thể hiện của loại 'System.Data.Objects.ObjectQuery`1 [DataModel.Table2 ] '

+4

Đây là câu trả lời toàn diện. Cảm ơn. – Nick

Các vấn đề liên quan