1

Я пытаюсь создать новую основную структуру (в основном веб-сайт) с шаблоном репозитория и единицы работы для моих приложений, которые я могу изменить для своего ORM в NHibernate или Dapper позже.Entity Framework, свойства навигации, репозиторий, блок работы, сменный ORM

Сейчас мой интерфейс Единица работы, как это:

public interface IUnitOfWork : IDisposable 
{ 
     void Commit(); 
     void Rollback(); 
} 

И реализация Entity Framework, как это (обрезается для удобства чтения)

public class EfUnitOfWork : IUnitOfWork 
{ 
    .... 
    public EfUnitOfWork(ApplicationDbContext context) 
    { 
     this._context = context; 
     this._transaction = new EfTransaction(_context.Database.BeginTransaction()); 
    } 

    public void Commit() 
    { 
     this._context.SaveChanges(true); 
     this._transaction.Commit(); 
     ... 
    } 

    public void Rollback() 
    { ... 
    } 
} 

Проблема заключается в том, что в моей службы слоя который содержит бизнес-логику, я могу сделать что-то подобное с навигационными свойствами:

public bool CreateCity(CityCreateModel model) 
     { 
      using (var uow = _unitOfWorkFactory.Create()) 
      { 
       var city = new City(); 
       city.Name = model.Name; 
       city.State = new State() { Country = new Country() { Name = "SomeCountry" }, Name = "SomeCity" }; 
       _cityRepository.Create(city); 
       try 
       { 
        uow.Commit(); 
        return true; 
       } 
       catch (Exception) 
       { 
        uow.Rollback(); 
        throw; 
       } 
      } 
     } 

Репозиторий Создать метод довольно прост, как я использую рамки сущности:

public void Create(City entity) 
    { 
     _set.Add(entity); 
    } 

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

Если я попытаюсь изменить существующий образец на Dapper.NET или на службу REST позже, может возникнуть много проблем, которые я должен был искать, для каждого свойства навигации и отслеживания, которые они были изменены или нет, и написать много (возможно, мусорного) кода для них, поскольку я действительно не знал, что вставлено в таблицу через сущность framework, и что isnt (из-за свойств навигации также вставлены и мои репозитории вызываются один раз только для 1 вставки, которая предназначена для City в моем примере выше)

Есть ли способ предотвратить это поведение или есть шаблон, известный, что я могу адаптироваться на раннем этапе, поэтому у меня не будет проблем позже?

Как вы преодолели это?

+1

Dapper - это легкий ORM, ориентированный главным образом на отображение объектов. Entity Framework (и NHibernate) - это полномасштабные ORM. Нет никакого способа написать больше кода, если вы используете Dapper вместо EF или NHibernate. Скорее всего, Dapper не подходит для ваших требований. –

+0

Однако, скажем, мне нужно изменить свои потребности в базе данных, и теперь я должен создавать/читать объекты из веб-службы, а не напрямую из базы данных. Я все еще не могу избежать добавления свойств навигации, я не могу контролировать, что позже будет добавлено в db/web-сервис. Ваш комментарий заставил меня понять, что я не уточнил свой вопрос, спасибо –

+0

Тогда ваши методы репозитория и методы API должны делать то же самое. Если они не знают, как создавать объекты состояния, тогда метод службы должен заменить новое состояние() чем-то другим. Просто будьте осторожны, потому что это начинает открывать ящик Пандоры, и уровень сложности может стать довольно высоким довольно быстро. –

ответ

1

Прежде чем начать, я хочу дать некоторые примечания к коду:

public EfUnitOfWork(ApplicationDbContext context) 
{ 
    this._context = context; 
    this._transaction = new EfTransaction(_context.Database.BeginTransaction()); 
} 

1) Из вашего примера я могу видеть, что вы используете один и тот же DbContext (учитывая в качестве параметра в constuctor для всего приложения Я не думаю, что это хорошая идея, потому что сущности будут кэшироваться в кеше первого уровня, а трекер отслеживания будет отслеживать их все. При таком подходе скоро появятся проблемы с производительностью, когда база данных будет расти.

_cityRepository.Create(city); 

public void Create(City entity) 
{ 
    _set.Add(entity); 
} 

2) Базовый репозиторий должен быть генератором eric типа T, где T - сущность! и вы можете создать город;

var city = _cityRepository.Create(); 
    Fill the city or provide the data as parameters in the create method. 

Возвращаясь к вашему вопросу:

Есть ли способ предотвратить такое поведение или есть шаблон известно, что я могу адаптироваться на ранней стадии, так что я не буду иметь проблемы в дальнейшем?

Каждый ОРМ имеет свою собственную концепцию Desgin, и это не так легко найти общий способ, который поместиться в них все, что так, как я бы сделать следующее:

1) Отдельные контракты репозиториев в одном сборки (контракты dll)

2) Для каждой ORM Framework используйте отдельную сборку, которая реализует контракты репозитория.

Пример:

public interface ICityRepository<City> :IGenericRepsotiory<City> 
{ 
    City Create(); 
    Find(); 
    .... 
} 
  • Сущность Frmework сборки:

    класс CityRepositoryEF общественности: ICityReposiory { ..

  • Щеголеватый Frmework сборки:

    общественного CLA сс CityRepositoryDapper: ICityReposiory { ..

+0

Я уже разделял контракты, а также разделял сборку для хранилищ каждой ормы. Это все еще не устраняет магию свойств внутренней навигации прямо сейчас (это также будет проблемой для метода обновления позже). Я по-прежнему рассматриваю изменения в вариантах, которые уже указывали ваши заметки. Спасибо за ваши драгоценные мнения. –

 Смежные вопросы

  • Нет связанных вопросов^_^