9

我在存储库方面有点挣扎。我正在使用 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.
}

两者似乎都有些错误。

什么是正确的方法?

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

感谢所有的回复。我无法决定谁是最正确的,因此无法决定接受哪个答案。

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

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

4

5 回答 5

6

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

在业务层,我有 userManager.registerUser(string username, /* params, etc */)。这将创建域对象。此方法只会调用add()数据层中的方法。

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

于 2009-06-09T16:48:29.573 回答
3

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

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

在场景 A) 中,您无法在不直接访问数据库的情况下使用正确的默认数据创建新用户。因此,我主张将所有业务逻辑保留在存储库之外,并采用您的第二个设计

于 2009-06-09T17:03:09.727 回答
2

确定您想要注册方法的位置,可能在 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
}
于 2009-06-09T17:07:46.867 回答
1

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

对于您的注册示例...您的服务方法将验证输入,构建用户对象,然后调用您的存储库以将您的新实体“添加”到“存储库”(可以是数据库...但也可以是别的东西……就您的域而言,没关系……它只是一个存储库。)

于 2009-06-09T17:08:40.937 回答
0

我看到了两个潜在的“错误”问题(因为您没有真正指出您认为它们有什么问题)。

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

  2. 如果问题围绕着在用户真正准备好概念性地保存东西之前保存东西,那么跟踪他们想要添加的内容并等到调用整体“保存”方法后再将任何这些信息放入存储中。

于 2009-06-09T17:07:16.073 回答