Given my IUnitOfWork
interface
using System;
public interface IUnitOfWork : IDisposable
{
void Commit();
}
I then create an abstract factory interface called IUnitOfWorkFactory
using System.Transactions;
public interface IUnitOfWorkFactory
{
IUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel);
}
I then create a default implementation of my IUnitOfWork
called TransactionScopeUnitOfWork
using System;
using System.Transactions;
public class TransactionScopeUnitOfWork : IUnitOfWork
{
private bool disposed = false;
private readonly TransactionScope transactionScope;
public TransactionScopeUnitOfWork(IsolationLevel isolationLevel)
{
this.transactionScope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = isolationLevel,
Timeout = TransactionManager.MaximumTimeout
});
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
this.transactionScope.Dispose();
}
disposed = true;
}
}
public void Commit()
{
this.transactionScope.Complete();
}
}
I then create the factory to return that implementation called TransactionScopeUnitOfWorkFactory
using System.Transactions;
public class TransactionScopeUnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel)
{
return new TransactionScopeUnitOfWork(isolationLevel);
}
}
The reason for creating the factory is to allow DI (Dependency Injection) frameworks to use different unit of work implementations depending on configuration.
If TransactionScopeUnitOfWorkFactory
was mapped to IUnitOfWorkFactory
in a DI container, some sample code for using it in an application could be:
public class Test
{
private readonly IUnitOfWorkFactory unitOfWorkFactory;
private readonly IRepository testRepository;
public Test(
IRepository testRepository,
IUnitOfWorkFactory unitOfWorkFactory)
{
this.testRepository = testRepository;
this.unitOfWorkFactory = unitOfWorkFactory;
using (IUnitOfWork unitOfWork = this.unitOfWorkFactory.GetUnitOfWork(IsolationLevel.Serializable))
{
this.testRepository.Delete(1); // Some valid CRUD
unitOfWork.Commit();
}
}
I am asking if this seems like a good implementation. Am I missing anything?
I want an IUnitOfWork
interface that I can use across applications and not worry about maintaining later on. Any opinions?