Al modificar el comandante LINQ-to-SQL, ¿debería cerrarse la conexión?
-
26-10-2019 - |
Pregunta
Estoy modificando el ComandoText de Linq a SQL para obligarlo a usar Nolock, así ...
if (db.Connection.State == System.Data.ConnectionState.Closed)
db.Connection.Open();
var cmd = db.GetCommand(db.Customers.Where(p => p.ID == 1));
cmd.CommandText = cmd.CommandText.Replace("[Customers] AS [t0]", "[Customers] AS [t0] WITH (NOLOCK)");
var results = db.Translate(cmd.ExecuteReader());
Es una aplicación MVC, por lo que el DataContext está en el controlador base, y puede haberse utilizado antes de este código y, lo que es más importante, después. ¿Debería cerrar la conexión en esta rutina? O no en absoluto? ¿O solo si lo abrí aquí?
Actualizar:
Ahora estoy usando la función más general (en la clase DataContext) para modificar el ComandoText y cerrar la conexión si se abrió aquí. Y el Abierto ha sido trasladado al ejecutor. Hasta ahora ha estado funcionando y reduciendo los problemas esporádicos de punto muerto. Los resultados no tienen que ser de inmediato.
public List<T> GetWithNolock<T>(IQueryable<T> query)
{
// to skip nolock, just...
// return query.ToList();
List<T> results = null;
bool opened = false;
try
{
if (Connection.State == System.Data.ConnectionState.Closed)
{
Connection.Open();
opened = true;
}
using (var cmd = GetCommand(query))
{
cmd.CommandText = Regex.Replace(cmd.CommandText, @"((from|inner join) \[dbo.*as \[t\d+\])", "$1 with (nolock)", RegexOptions.IgnoreCase);
results = Translate<T>(cmd.ExecuteReader()).ToList();
}
}
finally
{
if (opened && Connection.State == System.Data.ConnectionState.Open)
{
Connection.Close();
}
}
return results;
}
En el pasado, he encontrado que usar una transacción de la manera recomendada hace que el sitio se quede sin conexiones durante la noche. Hasta donde yo sé, ese es un error en Linq a SQL. Puede haber formas de evitarlo, pero estoy tratando de mantener mi código principal directo. Ahora "solo" tengo que hacer esto ...
var users = GetWithNolock<User>(
Users
.Where(u => my query
);
Solución
Si lo abres, debes cerrarlo. Otras operaciones de Linqtosql coinciden con este patrón.
En mi código, abro incondicionalmente la conexión y cierre la conexión en un finalmente. Si alguien me pasa una conexión abierta, es su culpa y lo cierro por ellos.
Puede retrasar la apertura de la conexión hasta justo antes de Ejecutorader.