8

Я немного борюсь с репозиториями. Я использую C# и NHibernate. Вопрос, который у меня есть, заключается в следующем: сколько должен делать мой репозиторий до того, как он назовет сохранение или получить?Сколько логических я должен поместить методы репозитория при использовании шаблона репозитория?

Например, у меня есть пользовательский класс, который является совокупным корнем. Я хочу вызвать метод «register», который добавит пользователя и установит некоторые значения по умолчанию на основе бизнес-правил и создаст некоторые другие объекты, которые также являются поднаборами «пользовательского» корня (то есть адреса, групп и т. Д.). Должен ли я позвонить

userRepo.Register(newUser); 

, который бы (не обращая внимания на очевидные проблемы):

Regsiter(User newUser){ 
newUser.SomeProp = "Default Data"; 
Group g= new Group; 
g.SomeProp2 = "Default Data"; 
newUser.Groups.Add(g); 
Session.Save(g); 
Session.Save(newUser); 
} 

или должен я поставил регистр в бизнес-уровне и имеют это делают:

Regsiter(User newUser){ 
newUser.SomeProp = "Default Data"; 
Group g= new Group; 
g.SomeProp2 = "Default Data"; 
newUser.Groups.Add(g); 
userRepo.Register(newUser, g);// this does session.save on both objects. 
} 

Оба кажется немного неправильным.

Каков правильный подход?

редактировать -------------------------------

спасибо за все ответы. Я не могу решить, кто из них наиболее прав, и поэтому ответ на него принимается.

Как правило, все говорят, что деловые правила в другом слое. это имеет смысл, но я не уверен в вызовах данных для групп. Поскольку группы не являются совокупным корнем, у них не должно быть собственного репозитория, так как я могу добавить и сохранить их? В моем проекте добавление группы в коллекцию групп пользователей автоматически не создает группу в db; Мне также нужно вызвать session.save на объекте. поэтому я помещаю это в пользовательский репо как userRepo.SaveGroup (g)?

Если у меня есть createGroup() на другом слое, тогда ему придется либо использовать собственный репо, либо пользователей. или я толстый?

ответ

3

Определите, где вы хотите, чтобы ваш метод Регистр, возможно, в классе UserServices. вы можете делегировать создание объекта к UserFactory. в CreateNewUser (), настройте свои значения по умолчанию для пользователя и коллекции групп. Затем вызовите UserRepository.Save (newUser), чтобы сохранить данные.

// UserServices class 
public void Register(User newUser) 
{ 
    // add custom registration stuff. 
    _userRepository.Save(newUser); 
} 

// Application code 
User user = UserFactory.CreateNewUser(); 
_userServices.Register(user); 

// UserFactory 
public User CreateNewUser() 
{ 
    // all new user, group creation 
} 
+0

в этом примере создание группы находится в userfactory. где происходит взаимодействие группы db взаимодействия? в групповом репо или пользовательском репо? –

+0

Всё зависит от: Может быть случай для группового репозитория. На практике попытайтесь ограничить репозитории на один на каждый общий корень. В таком случае используйте GroupRepository, чтобы найти существующую группу и передать Группу в качестве параметра в свой метод UserFactory.CreateNewUser. Когда UserRepository сохраняет пользователя, проверьте свою конфигурацию, чтобы убедиться, что вы также сохраняете ассоциацию групп. –

+1

В качестве альтернативы, может возникнуть смысл создать экземпляр нового объекта User и использовать метод UserServices.RegisterWithDefaultGroup (пользовательский пользователь) со следующей реализацией: Group defaultGroup = _groupRepository.FindByName («По умолчанию»); user.AddGroup (defaultGroup); Регистрация (пользователь); Это действительно зависит от вашего приложения, архитектуры программного обеспечения и от того, насколько вы строго придерживаетесь определенных принципов. Удачи! –

6

Лично я сохраняю шаблон репозитория в качестве замены для sprocs. Так что мой репозиторий будет иметь такие методы, как getById(int id), save(), add(DomainObject obj) и т.д.

В бизнес-уровне, я бы userManager.registerUser (строка имя пользователя/* Params, и т.д. * /). Это создаст объект домена. Этот метод просто вызовет метод add() в уровне данных.

Короче говоря, бизнес-уровень является бизнес-y, а уровень данных - данными.

+0

Основываясь на ваших именах методов, я бы сказал, что ваши «хранилища» фактически следуют шаблон «Data Mapper» из книги Fowlers PofEAA. Репозиторий от Domain Driven Design - это подобный сборке интерфейс, а не класс с определенными методами. – jrista

3

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

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

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

+0

Репозиторий не должен обрабатывать обновления. Он должен абстрагировать базу данных (или другую персистентность) данных в коллекции, подобной интерфейсу. Обычную коллекцию dotnet, такую ​​как список или словарь, не нужно знать об обновлениях. Также нет репозитория. – Paco

0

Я вижу две потенциальные проблемы «неполадки» (так как вы на самом деле не указали, что с ними было не так).

  1. Если проблема вращается вокруг сохранения группы в методе регистрации пользователя, или сохранение пользователя в групповых методах, то вы должны разделить их на различные методы. (например, Register() будет вызывать RegisterGroup() или GetGroup()

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

1

Из вашего примера кода я бы назвал метод Register функцией сервиса. В качестве сервисной операции он будет принадлежать службе или бизнес-компоненту, а не репозиторию. Согласно Evans (из славы DDD), репозиторий представляет собой наборный интерфейс для объектов, хранящихся в вашей базе данных. Общая идея заключается в том, что вы предоставляете базовый доступ к своим CRUD-объектам через репозиторий, чтобы абстрагировать остальную часть вашего кода от данных доступа к данным более низкого уровня, таких как инструмент ORM.

Для вашего примера с регистрацией ... ваш метод обслуживания будет проверять ввод, построить объект User, а затем вызвать ваш репозиторий для «добавления» вашего нового объекта в «репозиторий» (который может быть базой данных ... но также может быть что-то еще ... что касается вашего домена, это не имеет значения ... его просто репозиторий.)

+0

Является ли служебная операция внутри класса контроллера или бизнес-уровня? Или это то же самое, что и вы в этом случае? –

+0

Ну, я считаю, что контроллеры отличаются от служб. Контроллер является точкой доступа для взаимодействия человека ...и, как правило, они должны быть максимально легкими. Ваши контроллеры должны выполнять минимальную согласованность вызовов другим службам, упаковывать любые данные и направлять эти данные на просмотр, не более того. Службой может быть прикладная служба или бизнес-сервис. Службы приложений могут выполнять чисто работу на уровне приложений или составлять несколько бизнес-сервисов ... но служба - это основная часть вашего поведения, в том числе использование репозиториев. – jrista

+1

@ Charlie Bear: Посмотрите на Луновскую архитектуру Джеффри Палермо. Это то, что я использую для приложений в стиле DDD. Это может помочь объяснить, что происходит. Удачи! http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ –