4

我一直在开发一个应用程序,我试图aply DDD和其他工具(Nhibernate和asp.net MVC)。储存库基地或特定方法?

在这个应用程序中,我们有一个要求在存储库的Person实体中按名称执行'搜索'。所以,我们有一个仓库库(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 base(generic)的一些很好的实现?

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


更新:

如果我需要,例如,像一个复杂的搜索相结合的条件...如:名称(可选)和年龄(可选)和城市(可选)等领域......每个领域都是可选的,并与其他领域相结合!使用表达将是推荐的或不是?你将如何实现这个代码?

PS:Sorry for my english!

感谢

回答

4

为了有两全其美的,可以统称实现FindByName方法,你在基类中有,将其标记为protectedprotected internal(取决于你是否要允许其他组件来定义库的实现) ,然后从您的特定存储库对象调用它。

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); 
    } 
+0

是的,Ryan,我认为在这个解决方案中,我也是这样做的,但是看看这个代码(我的意思是......你选择了'保护内部'),我想如果有任何问题来保证它'公开',有什么问题吗?也许这听起来像做另一种选择,但我知道这不是建议。但是,您的解决方案很好,谢谢:D –

+0

我与受保护或受保护内部一起使用的原因是因为这可确保您的存储库的客户端不会直接调用FindAll方法。如果你公开了它,并且客户端使用了它,这将需要你从客户端的单元测试中测试Repository的功能,这将违背DDD。 –

+0

不错的解释瑞恩,我明白了,这听起来像是为了在存储库中返回IEnumerable insted IList的原因,用户可以执行与所讨论的点的目标不同的其他任务,如在IList中,此存储库的用户可以调用例如,“添加”方法。谢谢:D –

1

这两种方法的工作原理,我将使用通用的方法,但findmyname给你更好的和干净的代码。 我认为它是一种味道的问题,以及你想成为DDD的纯粹主义者。我会为更复杂的需求创建具体的方法,比如搜索或者其他的东西,但是保持简单就是为我提供的方式

+0

感谢奥斯卡,我的想法是一样的!但看看我的udpates。在这种情况下你会怎么做? –

1

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

+0

谢谢,我也同意!但看看我的更新!在这种情况下你会怎么做? –

1

其他注意事项:

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

接口有多臃肿?只是因为一个表达式可以几乎任何东西并不意味着它通常是。但在这种情况下,也许是因为您可以像更新中那样结合搜索标准,那么可以重新使用更抽象的方法,至少作为助手。

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

干杯,
Berryl

+0

我的GUI将使用此(asp.net mvc应用程序)。你将如何实现一个可选参数的方法来创建一个过滤器? (就像我在更新中说的)。感谢您的awryl Berryl –

+0

@Felipe。一般来说,我会使用扩展。这是[一般想法](http://statichippo.com/archive/2011/01/07/ORM-and-the-big-difference-between-IQueryable-and-IEnumerable.aspx) – Berryl

相关问题