在使用存储库模式时,我应该将我的存储库方法放多少逻辑?

时间:2009-06-09 16:41:31

标签: c# nhibernate domain-driven-design repository-pattern repository

我正在与存储库进行一些努力。我正在使用C#和NHibernate。我的问题是:我的存储库在调用save或get之前应该做多少?

例如,我有一个用户类,它是一个聚合根。我想调用一个名为“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.
}

两者似乎都有些错误。

什么是正确的方法?

编辑-------------------------------

感谢所有回复。我不能决定谁是最合适的,因此接受哪个答案。

通常每个人都在说将业务规则放在另一层。这是有道理的,但我不确定组的数据调用 - 因为组不是聚合根,他们不应该有自己的存储库,所以我如何添加和保存它们?在我的项目中,将一个组添加到用户的组集合中不会自动在数据库中创建该组;我还需要在对象上调用session.save。所以我把它作为userRepo.SaveGroup(g)放入用户仓库?

如果我在另一层有一个createGroup(),那么它需要使用它自己的repo或用户。还是我很厚?

5 个答案:

答案 0 :(得分:6)

就个人而言,我将存储库模式保留为sprocs的替代品。所以我的存储库会有getById(int id)save()add(DomainObject obj)等方法。

在业务层中,我有userManager.registerUser(字符串用户名,/ * params等* /)。这将创建域对象。此方法只需调用数据层中的add()方法。

简而言之,业务层是业务层,数据层是数据层。

答案 1 :(得分:3)

首先使用存储库模式的动机是什么?通常,存储库是对象持久性逻辑的抽象。它从(通常)数据库中检索项目,并处理更新,插入和删除。

如果您正在编写测试以检查某些逻辑并且不想访问数据库,那么您需要模拟哪些对象?通常是存储库。

在方案A)中,您无法测试使用正确的默认数据创建的新用户,而无需直接访问数据库。因此,我建议将所有业务逻辑保留在存储库之外,并使用第二个设计

答案 2 :(得分:3)

确定您想要Register方法的位置,可能在UserServices类中。您可以将对象创建委派给UserFactory。在CreateNewUser()方法中,为用户和Groups集合设置默认值。然后调用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
}

答案 3 :(得分:1)

从您的代码示例中,我将Register方法称为服务操作。作为服务操作,它将属于服务或业务组件,而不是存储库。根据Evans(DDD成名),存储库是存储在数据库中的实体的类似集合的接口。一般的想法是,您通过存储库提供对实体的基本CRUD访问,以便从ORM工具等较低级别的数据访问详细信息中抽象出其余代码。

对于您使用Register的示例...您的服务方法将验证输入,构建User对象,然后调用您的存储库以“添加”您的新实体到“存储库”(可能是一个数据库......但是也可能是其他东西......就你的域名而言,它并不重要......它只是一个存储库。)

答案 4 :(得分:0)

我看到两个潜在的“错误”问题(因为你并没有真正表明你认为他们的错误)。

  1. 如果问题围绕在用户注册方法中保存组,或者将用户保存在组方法中,则应将这些方法分成不同的方法。 (即Register()将调用RegisterGroup()或GetGroup()

  2. 如果问题围绕在用户真正准备从概念上保存内容之前保存内容,那么请跟踪他们想要添加的内容并等到调用整个“save”方法之后再放入任何此类信息进入存储。