Wenn die AsNoTracking
Methode in einer LINQ-Abfrage in Entity Framework verwendet wird, sollte sie für jede Tabelle oder die Abfrage als Ganzes verwendet werden, um die Änderungsnachverfolgung für die gesamte Abfrage zu deaktivieren.
1. Gegen die gesamte Abfrage
var query = (from t1 in db.Table1
from t2 in db.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1).AsNoTracking()
2. Gegen jeden Tisch
var query = (from t1 in db.Table1.AsNoTracking()
from t2 in db.Table2.AsNoTracking().Where(o => t1.ConditionId == o.ConditionId)
select t1)
Ich beabsichtige, die Änderungsnachverfolgung für die gesamte Abfrage zu deaktivieren, aber nicht für jede Tabelle verwenden zu wollen, wenn dies nicht erforderlich ist.
MSDN bezieht sich auf ein Abfrageobjekt in der Dokumentation für diese Methode:
Diese Methode funktioniert durch Aufrufen der AsNoTracking-Methode des zugrunde liegenden Abfrageobjekts. Wenn das zugrunde liegende Abfrageobjekt nicht über eine AsNoTracking-Methode verfügt, führt der Aufruf dieser Methode zu nichts.
Basierend auf einem Test, den ich gerade gemacht habe, sind beide Ergebnisse gleich. Die Verwendung von Table Level oder QueryLevel AsNoTracking führt dazu, dass keine Objekte in ChangeTracker eingeschlossen werden. Entitäten aus Table2 werden jedoch niemals in den ChangeTracker eingefügt, wie Sie im WithtoutAsNoTracking-Test sehen können.
Gehen Sie davon aus, dass Sie tatsächlich Daten von t1 und t2 abfragen. Ich habe einen Test hinzugefügt, wenn ich abfragee, dass alle Einträge noch mit einem einzigen AsNoTracking zur Abfrage hinzugefügt wurden, es wird kein Eintrag verfolgt. Wenn Sie AsNoTracking () direkt auf table1 ablegen, werden die Entitäten von table1 und table2 nicht verfolgt.
[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));
}
}
Ich habe auch das AsNoTracking From Table2 in der join-Klausel entfernt, da es eine Ausnahme verursachte.
System.ArgumentException: Methode 'System.Data.Entity.Infrastructure.DbQuery
1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery
1 [DataModel.Table2]' kann nicht mit Instanz von aufgerufen werden Typ 'System.Data.Objects.ObjectQuery`1 [DataModel.Table2]'