存储库基础或特定方法?

时间:2011-07-15 18:09:35

标签: .net nhibernate design-patterns domain-driven-design repository

我一直在开发一个应用程序,我正在尝试使用DDD和其他工具(Nhibernate和asp.net MVC)。

在这个应用程序中,我们需要在存储库的Person实体中通过Name实现“搜索”。所以,我们有一个存储库库(RepositoryBase类),在这个实现中我有一个适用于这个项目的通用方法。

public IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) {
  return Session.QueryOver<T>().Where(condition);
}

在我的asp.net mvc应用程序中,我们可以使用它:

var list = _repositoryPerson.FindAll(x => x.Name == "Felipe");

另一方面,我们可以为此任务创建一个特定的方法(在RepositroyPerson类中),如:

public IEnumerable<Person> FindByName(string name) {
  return Session.QueryOver<Person>().Where(x => x.Name == name);
}

在我的asp.net mvc应用程序中,我们可以使用它:

var list = _repositoryPerson.FindByName("Felipe");

我的问题是:

1 - 根据DDD满足此要求的推荐方法是什么?具体还是基类?

2 - 有人推荐使用Nhibernate QueryOver实现一些很好的Repository库(泛型)实现吗?

如果有人可以帮助我,我会非常感激! 感谢


更新

如果我需要,例如,复杂的搜索,例如组合条件......例如:名称(可选)和年龄(可选)和城市(可选)和其他字段....每个字段都是可选的并且组合与其他领域!建议使用表达式还是不建议?你会如何实现这个代码?

PS:对不起我的英文!

由于

4 个答案:

答案 0 :(得分:4)

为了充分利用这两个方面,您可以像在基类中一样实施FindByName方法,将其标记为protectedprotected internal(取决于是否您希望允许其他程序集定义Repository实现),然后从您的特定存储库对象中调用它。

protected internal IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) {
  return Session.QueryOver<T>().Where(condition);
}

public IEnumerable<Person> FindByName(string name) {
  return base.FindAll(x => x.Name == name);
}

这将允许您为将要使用该方法的案例编写特定测试,同时还允许您更改ORM实现,而无需在大量位置更改它。

更新: 为了在FindAll中组合多个条件,您可以使用Aggregate简单地组合它们(我没有用NHibernate测试它,但如果它中断了,你可以用foreach替换它)。

public IEnumerable<T> FindAll(IEnumerable<Expression<Func<T, bool>>> conditions)
{
    return conditions.Aggregate(Session.QueryOver<T>(), (current, condition) => current.Where(condition)).List();
}

然后方法可以使用可选参数,并创建传递给FindAll的条件列表。

   public IEnumerable<T> FindByParams(string name=null, string city=null)
   {
       var wheres = new List<Expression<Func<T, bool>>>();

       if (name != null)
       {
           wheres.Add(x => x.Name == name);
       }
       if (city != null)
       {
           wheres.Add(x => x.City == city);
       }
       return base.FindAll(wheres);
   }

答案 1 :(得分:1)

两种方法都可以使用泛型方法,但是findmyname可以为您提供更好,更干净的代码。 我认为这是一个品味问题,你想成为DDD的纯粹主义者。我将为更复杂的要求创建特定方法,例如搜索或其他东西,但保持简单是我的选择

答案 2 :(得分:1)

我同意奥斯卡 - 我更喜欢特定的方法,主要原因是它们更容易被测试。围绕IQueryable和Expression对象构建合理的测试非常具有挑战性。

答案 3 :(得分:1)

其他注意事项:

您的存储库代码的消费者是谁?如果您将您的存储库暴露给可能会挣扎或滥用更抽象的接口的gui或其他开发人员,那么还有额外的动机来提供更清晰的特定接口。

界面多么臃肿?仅仅因为表达式几乎可以并不意味着它通常是。但是在那些情况下,可能是因为你可以像在更新中那样组合搜索条件,然后再倾向于使用更抽象的方法,至少作为帮助者。

我个人赞成尽可能使用更具体的界面

干杯,
Berryl