I'm building WPF/MVVM application and I'm struggling implementing Unit of work pattern.
The part, about which I'm not sure is UnitOfWork
class. Here is my thought:
It's coupled with my repositories and MyDatabaseContext
. At first impression, it doesn't sound good. But, I think, UnitOfWork
should be coupled with DbContext
. Technically it should be named MyDatabaseUnitOfWork
. What do you think?
Unit of work:
public interface IUnitOfWork : IDisposable
{
int Complete();
ICustomerRepository Customers { get; }
IPhoneRepository Phones { get; }
IAddressRepository Address { get; }
}
public class UnitOfWork<TContext> : IUnitOfWork
where TContext : MyDatabaseContext, new()
{
public ICustomerRepository Customers { get; }
public IPhoneRepository Phones { get; }
public IAddressRepository Address { get; }
public UnitOfWork()
{
context = new TContext();
Customers = new CustomerRepository(context);
Phones = new PhoneRepository(context);
Address = new AddressRepository(context);
}
public int Complete()
{
return context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
}
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork Create()
{
return new UnitOfWork<MyDatabaseContext>();
}
}
Useage:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
try
{
UnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<IUnitOfWorkFactory, UnitOfWorkFactory>();
unityContainer.RegisterType<MainWindowViewModel>();
var window = new MainWindow()
{
DataContext = unityContainer.Resolve<MainWindowViewModel>()
};
window.Show();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
public class MainWindowViewModel : ObservableObject
{
private readonly IUnitOfWorkFactory unitOfWorkFactory;
public MainWindowViewModel(IUnitOfWorkFactory uowFactory)
{
unitOfWorkFactory = uowFactory;
}
private int DoSomething()
{
using (var unitOfWork = unitOfWorkFactory.Create())
{
}
}
}
Sample repository:
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> Get(Func<TEntity, bool> predicate);
IEnumerable<TEntity> GetAll();
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
public interface ICustomerRepository : IRepository<Customer>
{
IEnumerable<Customer> GetTopCustomers(int count);
}
internal class CustomerRepository : Repository<Customer>, ICustomerRepository
{
private MyDatabaseContext MyDatabaseContext => Context as MyDatabaseContext;
internal CustomerRepository(MyDatabaseContext context)
: base(context)
{
}
public IEnumerable<Customer> GetTopCustomers(int count)
{
return MyDatabaseContext.Customers.ToList();
}
}
Here is my second option: Is it necessary?
public interface IUnitOfWork : IDisposable
{
int Complete();
}
public interface IMyDatabaseUnitOfWork : IUnitOfWork
{
int Complete();
ICustomerRepository Customers { get; }
IPhoneRepository Phones { get; }
IAddressRepository Address { get; }
}
public class MyDatabaseUnitOfWork<TContext> : IMyDatabaseUnitOfWork
where TContext : MyDatabaseContext, new()
{
public ICustomerRepository Customers { get; }
public IPhoneRepository Phones { get; }
public IAddressRepository Address { get; }
public MyDatabaseUnitOfWork()
{
context = new TContext();
Customers = new CustomerRepository(context);
Phones = new PhoneRepository(context);
Address = new AddressRepository(context);
}
public int Complete()
{
return context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}