Al utilizar el método AsNoTracking
dentro de una consulta LINQ en Entity Framework, ¿debería usarse contra cada tabla o la consulta en su conjunto para deshabilitar el seguimiento de cambios para toda la consulta?
1. Contra toda la consulta.
var query = (from t1 in db.Table1
from t2 in db.Table2.Where(o => t1.ConditionId == o.ConditionId)
select t1).AsNoTracking()
2. Contra cada mesa
var query = (from t1 in db.Table1.AsNoTracking()
from t2 in db.Table2.AsNoTracking().Where(o => t1.ConditionId == o.ConditionId)
select t1)
Mi intención es deshabilitar el seguimiento de cambios para toda la consulta, pero no quiero usarlo en cada tabla si no es necesario.
MSDN se refiere a un objeto de consulta en la documentación para este método:
Este método funciona llamando al método AsNoTracking del objeto de consulta subyacente. Si el objeto de consulta subyacente no tiene un método AsNoTracking, entonces la llamada a este método no hará nada.
Basado en una prueba que acabo de hacer, ambos resultados son los mismos. el uso de Nivel de tabla o QueryLevel AsNoTracking da como resultado que no se retenga ninguna entidad en tine ChangeTracker. Pero de cualquier manera, las entidades de la Tabla 2 nunca se colocan dentro del Change Tracker, como se puede ver en la prueba WithtoutAsNoTracking.
Base en el supuesto de que, de hecho, está consultando datos de t1 y t2. He agregado una prueba cuando estoy consultando que todas las entradas siguen con un solo AsNoTracking agregado a la consulta, no se rastrea ninguna entrada. Aún así, si coloca el AsNoTracking () directamente en la tabla 1, las entidades de tabla1 y de tabla2 no se rastrearán.
[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));
}
}
Además, he eliminado el AsNoTracking From Table2 dentro de la cláusula de unión porque estaba causando una excepción.
System.ArgumentException: Método 'System.Data.Entity.Infrastructure.DbQuery
1[DataModel.Table12 AsNoTracking()' declared on type 'System.Data.Entity.Infrastructure.DbQuery
1 [DataModel.Table2]' no se puede llamar con la instancia de escriba 'System.Data.Objects.ObjectQuery`1 [DataModel.Table2]'