.net 存储库库还是特定方法?

.net 存储库库还是特定方法?,.net,nhibernate,design-patterns,domain-driven-design,repository,.net,Nhibernate,Design Patterns,Domain Driven Design,Repository,我一直在开发一个应用程序,我正在尝试应用DDD和其他工具(Nhibernate和asp.NETMVC) 在这个应用程序中,我们需要在存储库的Person实体中按名称实现“搜索”。因此,我们有一个存储库库库(RepositoryBase类),在这个实现中,我有一个通用的方法来处理这个项目 public IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) { return Session.Qu

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

在这个应用程序中,我们需要在存储库的Person实体中按名称实现“搜索”。因此,我们有一个存储库库库(RepositoryBase类),在这个实现中,我有一个通用的方法来处理这个项目

public IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) {
  return Session.QueryOver<T>().Where(condition);
}
另一方面,我们可以为此任务创建一个特定的方法(在RepositroyPerson类中),如:

public IEnumerable<Person> FindByName(string name) {
  return Session.QueryOver<Person>().Where(x => x.Name == name);
}
我的问题是:

1-根据DDD,满足该要求的推荐方法是什么?特定类还是基类

2-有人推荐使用Nhibernate QueryOver实现一些不错的存储库库(通用)

如果有人能帮助我,我将非常感激! 谢谢


更新:

例如,如果我需要一个复杂的搜索,比如组合条件。。。e、 g:姓名(可选)、年龄(可选)、城市(可选)和其他字段。。。。每个字段都是可选的,并与其他字段合并!是否建议使用表达式?您将如何实现此代码

PS:对不起我的英语


谢谢

这两种方法都有效,我将使用泛型方法,但findmyname为您提供了更好、更清晰的代码。
我认为这是一个品味的问题,以及你想成为DDD的纯粹主义者。我会为更复杂的需求创建特定的方法,比如搜索或其他什么,但对我来说保持简单是一种方法

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

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

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);
}
<代码>受保护的内部IEnumerable FindAll(表达式条件){ return Session.QueryOver().Where(条件); } 公共IEnumerable FindByName(字符串名称){ 返回base.FindAll(x=>x.Name==Name); } 这将允许您为将要使用该方法的情况编写特定的测试,同时还允许您更改ORM实现,而无需在很多地方进行更改

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

public IEnumerable FindAll(IEnumerable条件)
{
返回conditions.Aggregate(Session.QueryOver(),(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);
   }
公共IEnumerable FindByParams(字符串名称=null,字符串城市=null) { var wheres=新列表(); if(name!=null) { 其中.Add(x=>x.Name==Name); } 如果(城市!=null) { 式中.Add(x=>x.City==City); } 返回基地FindAll(地点); }
其他注意事项:

谁是您的存储库代码的使用者?如果您将存储库暴露给gui或其他可能难以使用或误用更抽象界面的开发人员,那么就有额外的动机来提供更清晰的特定界面

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

我个人倾向于尽可能使用更具体的界面

干杯,

Berryl

是的,Ryan,我也认为在这个解决方案中,我做到了,但是看看这个代码(我的意思是……你选择了“内部保护”),我在想,如果让它“公开”有什么问题,有什么问题吗?也许这听起来像是做某事的另一种选择,但我知道它不推荐。但是你的解决方案很好,谢谢:我之所以选择protected或protected internal,是因为这样可以确保你存储库的客户端不会调用FindAll meth直接od。如果您将其公开,并且客户机使用了它,这将要求您从客户机的单元测试中测试存储库的功能,这将违反DDD。nice explain Ryan,我明白了,这听起来像是在存储库中返回IEnumerable insted IList的原因,用户可以执行与obje不同的其他任务关于这一点,例如在IList中,该存储库的用户可以调用“Add”方法。谢谢:DRyan,您将如何在ddd中实现可选过滤器,就像我在“更新”中所说的那样在第一篇帖子上?谢谢,伙计!谢谢,我也同意!但是看看我的更新!在这种情况下你会怎么做?谢谢奥斯卡,我也这么想!但是看看我的udpates。在这种情况下你会怎么做?我的GUI将使用这个(asp.net mvc应用程序)。你会如何实现一个带有可选参数的方法来制作过滤器?(就像我在更新中说的那样).谢谢你的提醒Berryl@Felipe.一般来说,我会使用扩展
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);
}
public IEnumerable<T> FindAll(IEnumerable<Expression<Func<T, bool>>> conditions)
{
    return conditions.Aggregate(Session.QueryOver<T>(), (current, condition) => current.Where(condition)).List();
}
   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);
   }