c# - net - pomelo entity framework
Obtenga Entity Framework 6 use NOLOCK en sus instrucciones SELECT debajo de (3)
En primer lugar ... NUNCA debe utilizar NOLOCK para todas y cada una de las declaraciones SQL. Podría comprometer la integridad de sus datos.
Es como cualquier otra consulta que sugiera un mecanismo que solo debe usar cuando hace algo fuera de lo común.
No hay forma de decirle al proveedor de EF que muestre la sugerencia de NoLock. Si realmente necesita leer datos no confirmados, tiene la siguiente opción.
Escriba su propio proveedor EntityFramework.
Utilice un Interceptor de comandos para modificar la instrucción antes de que se ejecute. http://msdn.microsoft.com/en-us/data/dn469464.aspx
Utilice un TransactionScope con IsolationLevel.ReadUncommited.
Sé que usted dijo que no quiere usar Transacciones, pero es la única forma inmediata de leer datos no confirmados. Además, no produce mucha sobrecarga ya que cada declaración en SQL Server se ejecuta "implícitamente" en una transacción.
using (new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
}))
{
using (var db = new MyDbContext()) {
// query
}
}
EDITAR: Es importante tener en cuenta también que NOLOCK para actualizaciones y eliminaciones (las selecciones permanecen intactas) ha sido desaprobado por Microsoft a partir de SQL Server 2016 y se eliminará en una versión futura.
Estoy utilizando Entity Framework 6 en un proyecto MVC 5. Como sabe, las consultas de SELECT
en SQL Server funcionan más rápido y más eficientemente si usamos WITH (NOLOCK)
en ellas. Revisé algunas sentencias de SQL SELECT generadas por Entity Framework 6 y me di cuenta de que ninguna de ellas contiene NOLOCK.
No quiero usar transacciones en mis operaciones de recuperación para leer de transacciones no confirmadas.
¿Cómo puedo hacer que EF 6 use NOLOCK en las sentencias SELECT que se encuentran debajo?
Estoy de acuerdo con lo que dice Codeworx de una manera en que Leer no comprometido puede ser peligroso. Si puedes vivir con lecturas sucias, hazlo.
Encontré una manera de hacer que esto funcione sin cambiar nada en las consultas actuales.
Necesitas crear un DbCommandInterceptor como este:
public class IsolationLevelInterceptor : DbCommandInterceptor
{
private IsolationLevel _isolationLevel;
public IsolationLevelInterceptor(IsolationLevel level)
{
_isolationLevel = level;
}
//[ThreadStatic]
//private DbCommand _command;
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
SetTransaction(command);
}
public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
SetTransaction(command);
}
public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
SetTransaction(command);
}
private void SetTransaction(DbCommand command)
{
if (command != null)
{
if (command.Transaction == null)
{
var t = command.Connection.BeginTransaction(_isolationLevel);
command.Transaction = t;
//_command = command;
}
}
}
}
luego, en el cctor (controlador estático de su dbcontext) simplemente agregue el interceptor a la DbInfrastructure de las colecciones de la estructura de la entidad.
DbInterception.Add(new IsolationLevelInterceptor());
Esto se aplicará a cada comando que EF envíe a la tienda y se ajustará a una transacción con ese nivel de aislamiento.
En mi caso, funcionó bien, ya que escribimos datos a través de una API donde los datos no se basan en las lecturas de la base de datos. (los datos pueden estar dañados debido a las lecturas sucias) y así funcionó bien.
Puede utilizar una solución alternativa que no utilice los ámbitos de transacción para cada consulta. Si ejecuta el código a continuación, ef utilizará el mismo nivel de aislamiento de transacción para la misma ID de proceso del servidor. Dado que la ID del proceso del servidor no cambia en la misma solicitud, solo una llamada para cada solicitud es suficiente. Esto también funciona en EF Core.
this.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");