.net core - тип репозитория единиц работы - PullRequest
0 голосов
/ 21 сентября 2018

Я хочу перенести большой проект, который собирает информацию о продуктах.Текущее приложение использует CSLA в качестве своей структуры (традиционные формы aspx).

Я хочу перенести / разработать приложение на .net core 2.1.У меня есть опыт разработки в MVC (4+ года) и недавнее знакомство с ядром .net.

Я хочу использовать EF Core для вызова существующих хранимых процедур.Я смотрю на использование универсального шаблона проектирования хранилища Unit of Work.Я использовал шаблон хранилища и нашел его очень полезным.

Как часть функциональности, которая существует в текущем процессе, она содержит основную таблицу и формат структуры таблицы правок.Когда кто-либо редактирует продукт, в таблицу «Редактирует» добавляется новая строка.После одобрения администратором, он вставляет / обновляет текущую строку в главной таблице.

Сработало ли использование 'Unit of Work / универсального шаблона репозитория' для других разработчиков в .net core 2.1?

С какими проблемами вы столкнулись?Моя цель - создать высокопроизводительное эффективное управляемое приложение.

Любые другие мысли и предложения приветствуются.Спасибо.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Я иду с классическим "это зависит".По сути, DbSet<> является хранилищем, а DbContext является единицей работы.Но это не означает, что вы не можете использовать шаблон репозитория или шаблон рабочей единицы на более высоком уровне абстракции.

Мой совет: не используйте его, пока он вам не понадобится.Я использовал единицу или схему работы с EF Core и нашел ее очень полезной в ситуации, когда вы работаете с несколькими DbContext s или несколькими поставщиками баз данных.Я не нашел другого экземпляра для его использования.

Я обычно не использую универсальный репозиторий, потому что я предпочитаю инкапсулировать свои запросы и не пускать их в мои Controller или Pages,


Обновлено, чтобы ответить на комментарий ниже:

Это отличный вопрос, на который не так легко ответить, и, конечно, он выходит за рамки StackOverflow.com, потому что мастерство обычно считается мнением,Есть стек обмена для вопросов, непосредственно связанных с мастерством кода https://softwareengineering.stackexchange.com.

Я, однако, скажу, как я рад, что вы хотя бы поднимаете вопрос.

Мое личное мнение состоит в том, чтобыРекомендовать «Проектирование на основе доменов». На эту тему есть много бесплатных ресурсов, но источником информации будет книга Эрика Эванса.

По сути, ваша бизнес-логика является ядром, и все зависимости указывают внутрь.Так что даже в «сервисном слое» не будет вашей бизнес-логики.

0 голосов
/ 21 сентября 2018

Лично я использую Единицу работы, чтобы уменьшить количество инъекций зависимостей.У меня может быть Единица работы базы данных, и как только я использую Инъекцию зависимостей для внедрения контекста Базы данных в эту Единицу работы, мне не нужно внедрять каждый репозиторий модели, где я хочу их использовать, а просто получаю доступ к репозиториям изединица работы.Это также помогает мне создавать экземпляры репозитория только тогда, когда он мне нужен определенным способом.

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);

...