Должны ли репозитории использовать тот же экземпляр контекста в Entity Framework 1.0 - PullRequest
2 голосов
/ 23 июня 2010

Я начал смотреть на Entity Framework для проекта, который я делаю, и иду по пути использования BLL против него через шаблон репозитория.Насколько я понимаю, для каждой сущности я должен создать для нее репозиторий, чтобы у меня были

public class UserRepository : IRepository<User>
{ ... }

и

public class AccountRepository : IRepository<Account>
{ ... }

С примерами, которые я видел, обычной практикой является созданиеконтекст сущностей в операторе using и выполнение операций получения, обновления и сохранения и т. д. в пределах.

using(var ctx = new AppEntities()
{
    //do whatever
    ctx.SaveChanges();
}

Для простого доступа к репозиторию это было бы хорошо, но что, если бы я хотел составить взаимодействие между 2 (илидалее) репозитории внутри BLL ...

public void SaveSomethingMoreComplex()
{
    //BLL here stuff like validation etc

    _userRepository.GetSomeData();
    _accountRepository.SaveSomeData(account);
    _userRepository.SaveSomeMore(user);

    // Probably should have one final save that affects both repositories???
    // Should be in a transaction scope also?
}

Было бы лучше использовать один и тот же экземпляр AppEntities для обоих репозиториев?

Также в этом примере, вероятно, должно быть окончательное сохранениев конце блока, вместо того, чтобы иметь 2, как в моем примере, и часть транзакции?

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

Спасибо за любую помощьпри условии.

Ответы [ 2 ]

3 голосов
/ 23 июня 2010

Это на самом деле не такая уж и необычная проблема при работе с шаблоном Repository, и он сводится к тому, чтобы предоставить способ явного управления жизненным циклом вашей единицы работы (что в случае с структурой сущностей является вашим контекстом),

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

В контексте Windows / Service вы, вероятно, захотите установить какое-то явное управление жизненным циклом для вашего подразделения или работы, чтобы вы могли определить область действия UoW на основе того, что выделают.Мне нравится метафора Conversation для переноса операций UoW, что означает, что я могу использовать что-то вроде этого:

using(Conversation.Start())
{
    // mess with the entities
} // Dispose on the object returned from Start will 
  // Save Changes and close the session

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

Что касается реализации, то это зависит от вашей инфраструктуры.Обычно я использую контейнер IoC, поэтому мне нужно будет Conversation.Start() создать для меня свою единицу работы и настроить IoC для возврата этого конкретного экземпляра, поэтому, когда я создаю свои репозитории, они получают текущий UoW.Вы также можете создать некоторые фабричные методы для беседы, чтобы вы могли получить экземпляры репозитория из беседы.Тип зависит от API, который вы хотите иметь доступным.

Надеюсь, это поможет.

0 голосов
/ 23 июня 2010

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

Если я собираюсь добавить новые функциональные возможности в репозиторий, то, вероятно, я захочу позже, чтобы это было доступно на самой сущности, поэтому я создаю частичные классы, которые содержат этот тип бизнес-логики. Таким образом я могу сделать что-то вроде ShoppingCart.AddProduct (int id) и выполнить логику в частичном классе.

Еще один распространенный сценарий - создание моделей одноразового просмотра. На самом деле это мои предпочтения.

http://blogs.msdn.com/b/dphill/archive/2009/01/31/the-viewmodel-pattern.aspx

Просто помните, что ваша сущность в Entity Framework уже является абстракцией источника данных или может отличаться от LINQ To SQL, где это сопоставление источника данных один к одному.

...