first - Ámbito de AsNoTracking dentro de la consulta LINQ en Entity Framework
entity framework nuget (1)
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 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 haya entidades retenidas en el 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 efectivamente 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]''