Лично я использую Единицу работы, чтобы уменьшить количество инъекций зависимостей.У меня может быть Единица работы базы данных, и как только я использую Инъекцию зависимостей для внедрения контекста Базы данных в эту Единицу работы, мне не нужно внедрять каждый репозиторий модели, где я хочу их использовать, а просто получаю доступ к репозиториям изединица работы.Это также помогает мне создавать экземпляры репозитория только тогда, когда он мне нужен определенным способом.
public interface IDatabaseUnitOfWork
{
DbContext DatabaseContext { get; }
Task<bool> Save();
IBaseRepository<UserAccount> UserAccountRepository { get; }
}
public class DatabaseUnitOfWork : IDatabaseUnitOfWork
{
private IBaseRepository<UserAccount> _userAccountRepository;
public DatabaseUnitOfWork(DbContext databaseContext)
{
DatabaseContext = databaseContext;
}
public DbContext DatabaseContext { get; private set; }
public async Task<bool> Save()
{
try
{
int _save = await DatabaseContext.SaveChangesAsync();
return await Task.FromResult(true);
}
catch (System.Exception e)
{
return await Task.FromResult(false);
}
}
public IBaseRepository<UserAccount> UserAccountRepository
{
get
{
if (_userAccountRepository == null)
{
_userAccountRepository = new BaseRepository<UserAccount>(DatabaseContext);
}
return _userAccountRepository;
}
}
}
Затем
services.TryAddSingleton<IDatabaseUnitOfWork, DatabaseUnitOfWork>();
services.TryAddSingleton<IServiceUnitOfWork, ServiceUnitOfWork>();
Наконец
public class DemoClass
{
private IServiceUnitOfWork _serviceUnitOfWork;
public DemoClass(IServiceUnitOfWork serviceUnitOfWork)
{
_serviceUnitOfWork = serviceUnitOfWork;
}
Public bool CreateUserAccount(UserAccount userAccount){
await _serviceUnitOfWork.UserAccountRepository.Add(userAccount);
return await _serviceUnitOfWork.Save();
}
----
}
ОБНОВЛЕНИЕ
ОБЩЕЕ БАЗОВОЕ Хранилище
public interface IBaseRepository<T> where T : class
{
Task<bool> Add(T entity);
Task<List<T>> GetAll();
Task<List<T>> GetAll(params Expression<Func<T, object>>[] includes);
Task<List<T>> SearchBy(Expression<Func<T, bool>> searchBy, params Expression<Func<T, object>>[] includes);
Task<T> FindBy(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes);
Task<bool> Update(T entity);
Task<bool> Delete(Expression<Func<T, bool>> identity, params Expression<Func<T, object>>[] includes);
Task<bool> Delete(T entity);
}
public class BaseRepository<T> : IBaseRepository<T> where T : class
{
private DbContext _ctx;
public BaseRepository(DbContext context)
{
_ctx = context;
}
public virtual async Task<bool> Add(T entity)
{
try
{
_ctx.Set<T>().Add(entity);
return await Task.FromResult(true);
}
catch (Exception e)
{
return await Task.FromResult(false);
}
}
public virtual async Task<List<T>> GetAll()
{
return _ctx.Set<T>().ToList();
}
public virtual async Task<List<T>> GetAll(params Expression<Func<T, object>>[] includes)
{
var result = _ctx.Set<T>().Where(i => true);
foreach (var includeExpression in includes)
result = result.Include(includeExpression);
return await result.ToListAsync();
}
public virtual async Task<List<T>> SearchBy(Expression<Func<T, bool>> searchBy, params Expression<Func<T, object>>[] includes)
{
var result = _ctx.Set<T>().Where(searchBy);
foreach (var includeExpression in includes)
result = result.Include(includeExpression);
return await result.ToListAsync();
}
/// <summary>
/// Finds by predicate.
/// http://appetere.com/post/passing-include-statements-into-a-repository
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <param name="includes">The includes.</param>
/// <returns></returns>
public virtual async Task<T> FindBy(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes)
{
var result = _ctx.Set<T>().Where(predicate);
foreach (var includeExpression in includes)
result = result.Include(includeExpression);
return await result.FirstOrDefaultAsync();
}
public virtual async Task<bool> Update(T entity)
{
try
{
_ctx.Set<T>().Attach(entity);
_ctx.Entry(entity).State = EntityState.Modified;
return await Task.FromResult(true);
}
catch (Exception e)
{
return await Task.FromResult(false);
}
}
public virtual async Task<bool> Delete(Expression<Func<T, bool>> identity, params Expression<Func<T, object>>[] includes)
{
var results = _ctx.Set<T>().Where(identity);
foreach (var includeExpression in includes)
results = results.Include(includeExpression);
try
{
_ctx.Set<T>().RemoveRange(results);
return await Task.FromResult(true);
}
catch (Exception e)
{
return await Task.FromResult(false);
}
}
public virtual async Task<bool> Delete(T entity)
{
_ctx.Set<T>().Remove(entity);
return await Task.FromResult(true);
}
}
РАСШИРЕНИЕ БАЗОВОГО Хранилища (например, DeleteAllAccounts )
public interface IUserAccountRepository : IBaseRepository<UserAccount>
{
Task DeleteAllAccounts();
}
public class UserAccountRepository : BaseRepository<UserAccount>, IUserAccountRepository
{
private DbContext _databaseContext;
public UserAccountRepository(DbContext databaseContext) : base(databaseContext)
{
_databaseContext = databaseContext;
}
public async Task DeleteAllAccounts()
{
......
}
}
Так что вместо использования_userAccountRepository = new BaseRepository<UserAccount>(DatabaseContext);
вы бы использовали _userAccountRepository = new UserAccountRepository(DatabaseContext);