Error de base de datos bloqueada al utilizar BeginTransaction, múltiples repositorios, SQLite, UnitOfWork y Dapper.
Estoy intentando implementar transacciones con SQLite y Dapper pero recibo el error “la base de datos está bloqueada”.
Estoy usando el patrón UnitOfWork sugerido aquí.
Este es el código:
Controller.cs:
“`
public async Task MyMethodAsync()
{
//inyectando unitOfWork pero esta es la implementación
var unitOfWork = new UnitOfWork(new SQLiteConnection(“Data Source=TestDb;Mode=Memory;Cache=Shared”));
using (var connection = unitOfWork.Connection)
{
connection.Open();
unitOfWork.Begin();
var myFirstRepository = new MyFirstRepository(unitOfWork);
var mySecondRepository = new MySecondRepository(unitOfWork);
try
{
myFirstRepository.CreateStuff(); //aquí arroja la excepción "la base de datos está bloqueada"
mySecondRepository.CreateOtherStuff();
unitOfWork.Commit();
}
catch(Exception e)
{
unitOfWork.Rollback();
throw;
}
}
}
MyFirstRepository.cs:
public class MyFirstRepository
{
private IUnitOfWork _unitOfWork;
public MyFirstRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void CreateStuff()
{
using (var connection = _unitOfWork.Connection)
{
connection.Open();
await connection.ExecuteAsync("INSERT INTO ...", param).ConfigureAwait(false);
}
}
}
MySecondRepository.cs:
Implementación similar a MyFirstRepository.cs.
¿Alguien tiene alguna idea de lo que me estoy perdiendo aquí?
davy.ai
El problema aquí es que la conexión se está abriendo dos veces, una vez en el controlador y otra vez en el repositorio. Dado que SQLite solo admite una conexión de escritura a la vez, la base de datos queda bloqueada al abrir la conexión en el controlador y el repositorio al mismo tiempo. Para solucionar este problema, elimine la apertura de la conexión de los repositorios e inyecte la instancia de conexión en el constructor del repositorio. Luego, abra la conexión en el controlador y pase la instancia de conexión abierta a los repositorios. Aquí está el código actualizado:
Controller.cs:
MyFirstRepository.cs:
MySecondRepository.cs:
Al abrir la conexión solo una vez en el controlador y compartirla entre los repositorios, nos aseguramos de que solo se use una conexión de escritura a la vez y evitamos el error “la base de datos está bloqueada”.