Обновить концепцию репозитория - PullRequest
0 голосов
/ 07 июня 2018

В настоящее время я создаю приложение для проверки концепции, которое реализует шаблон хранилища.Я решил использовать классические ADO.NET и Entity Framework в качестве моих образцов ORM.В настоящее время так реализованы мои интерфейсы IRepository и IUnitOfWork.

public interface IUnitOfWork : IDisposable
{
    IEmployeeRepository Employees { get; }

    int Complete();
}

public interface IRepository<TEntity> where TEntity : class
{
    TEntity Get(int id);
    IEnumerable<TEntity> GetAll();
    IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);

    TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate);

    void Add(TEntity entity);
    void AddRange(IEnumerable<TEntity> entities);

    void Remove(TEntity entity);
    void RemoveRange(IEnumerable<TEntity> entities);
}

В моей реализации Entity Framework все хорошо для обновления объектов, поскольку в нем есть встроенный класс ChangeTracker , который проверяетсостояния объектов.

static void Main(string[] args)
{
    var context = new RPContextDbFactory().CreateDbContext(null);

    using (var unitOfWork = new Data.EF.UnitOfWork(context))
    {
        //using Entity Framework
        var employee = unitOfWork.Employees
            .Get(1);
        employee.FirstName = "Foo";

        unitOfWork.Complete(); // <-- Calls DbContext.SaveChanges()
    }
}

Моя проблема в том, как я могу реализовать ту же концепцию в классической реализации ADO.NET, поскольку у нее нет класса ChangeTracker, такого как EF.

static void Main(string[] args)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

    IConfigurationRoot configuration = builder.Build();


    var connectionString = configuration.GetConnectionString("RPContext");

    using (var unitOfWork = new Data.StoredProcedures.UnitOfWork(connectionString))
    {
        //using classic ADO.NET
        var employee = unitOfWork.Employees
            .Get(1);
        employee.FirstName = "Foo";

        unitOfWork.Complete(); //<-- Nothing will happen. 
    }
}

//UnitOfWork implementation for my classic ADO.NET
public class UnitOfWork : IUnitOfWork
{
    public UnitOfWork(string connectionString)
    {
        Employees = new EmployeeRepository(connectionString);
    }

    public IEmployeeRepository Employees { get; private set; }

    public int Complete()
    {
        throw new NotImplementedException();
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}

Один из советов, которые я видел на других сайтах, состоял в том, чтобы реализовать своего рода логику ChangeTracker в классе UnitOfWork моего пространства имен ADO.NET, но я не совсем уверен, как это реализовать.Как мой UoW узнает, какие объекты были изменены?

1 Ответ

0 голосов
/ 07 июня 2018

Я не понимаю необходимости использования как ADO.NET, так и EF.Один EF должен делать.

В любом случае, я рекомендую НЕ реализовывать UoW самостоятельно для ADO.NET.Это много работы и ошибок, и, наконец, вы обнаружите, что сделали все это неправильно.Если вы действительно хотите использовать UoW, используйте вместо этого EF (или NHibernate или еще).Зачем изобретать велосипед?Если вы решите реализовать его самостоятельно, вы на самом деле пишете свой собственный ORM, который считается антишаблоном .

Если вы хотите реализовать функцию UPDATE с использованием ADO.NET, тогда вы можете простореализовать метод void Update(TEntity entity); в вашем IRepository и вызывать его явно из вызывающего кода.Не включайте IUnitOfWork, чтобы сделать это автоматически.

Редактировать: Ответы на некоторые ваши комментарии -

Классический ADO.NET ORM не имеетИменно поэтому у меня возникают проблемы с обновлением объектов.

ADO.NET не является ORM.Это простой и основной API для взаимодействия с RDBMS.Все ORM используют его для внутреннего использования.

это также устраняет одну из ключевых целей шаблона репозитория, которая заключается в отделении вашего приложения от любых структур ORM.

Нет, скрытиеORM не является целью репозитория.Абстракция логики базы данных есть.Сделав это, вы можете смоделировать репозиторий, и ваш другой код станет тестируемым.Переключение ORM - довольно редкое решение.Хранилище делает этот процесс простым;конечно.Но все же, это не является обязанностью Репозитория.На самом деле, репозиторий не имеет никакого отношения к ORM или нет.

Шаблон репозитория должен быть реализован для всех из них.

Это может быть;в зависимости от потребностей бизнеса.Полные ORM, такие как EF, сами по себе являются репозиторием.Так что это дизайнерское решение, стоит ли добавить еще одну абстракцию над ним.Некоторые добавляют это;некоторые предпочитают использовать ORM напрямую.Оба подхода имеют свои преимущества и недостатки.

Создание метода обновления некорректно, поскольку ваш репозиторий не должен интересоваться семантикой вашей базы данных.

Вы должны внедрить ORMсебя тогда.Многие ORM с открытым исходным кодом.См. Код Dapper-Contrib на Git Hub.Он поддерживает ограниченное UoW;хорошо начать.Надеюсь, что это может помочь вам.

Я все еще настаиваю (исходя из собственного опыта), чтобы не разрабатывать собственную ORM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...