Nhibernate 具有通用方法的单个存储库。。。坏主意?

Nhibernate 具有通用方法的单个存储库。。。坏主意?,nhibernate,generics,fluent-nhibernate,repository,repository-pattern,Nhibernate,Generics,Fluent Nhibernate,Repository,Repository Pattern,我目前正在尝试在我所从事的项目中实现存储库的几种不同方法,目前有一个单一的存储库,上面有一些通用方法,如下所示: public interface IRepository { T GetSingle<T>(IQueryBase<T> query) where T : BaseEntity; IQueryable<T> GetList<T>(IQueryBase<T> query) where T : BaseEntit

我目前正在尝试在我所从事的项目中实现存储库的几种不同方法,目前有一个单一的存储库,上面有一些通用方法,如下所示:

public interface IRepository
{
    T GetSingle<T>(IQueryBase<T> query) where T : BaseEntity;

    IQueryable<T> GetList<T>(IQueryBase<T> query) where T : BaseEntity;

    T Get<T>(int id) where T : BaseEntity;

    int Save<T>(T entity) where T : BaseEntity;

    void DeleteSingle<T>(IQueryBase<T> query) where T : BaseEntity;

    void DeleteList<T>(IQueryBase<T> query) where T : BaseEntity;
}
公共接口IRepository
{
T GetSingle(IQueryBase查询),其中T:BaseEntity;
IQueryable GetList(IQueryBase查询),其中T:BaseEntity;
T Get(int id),其中T:BaseEntity;
int Save(T实体),其中T:BaseEntity;
void DeleteSingle(IQueryBase查询),其中T:BaseEntity;
void DeleteList(IQueryBase查询),其中T:BaseEntity;
}
这样,我就可以将一个存储库注入到一个类中,并使用它来获取我需要的任何东西

(顺便说一句,我使用Fluent NHibernate作为我的ORM,每个web请求有一个会话模式,并使用Structuremap注入我的存储库)

这似乎对我有用——我在这个存储库中定义的方法满足了我的所有需要。但在我所有的网络搜索中,我没有发现其他人使用这种方法,这让我觉得我遗漏了一些东西。。。随着应用程序的增长,这会给我带来问题吗

我读过很多人谈论每个根实体都有一个存储库——但是如果我用一些接口标识根实体,并限制泛型方法只允许类实现该接口,那么我不是也实现了同样的目标吗


提前感谢您提供的任何服务。

我已经在一些项目中成功地使用了这种方法。对于每个BaseEntity,将许多
IRepository
传递到我的服务层是一件很麻烦的事情,但它是有效的。我要更改的一件事是将
where T:
放在接口上,而不是方法上

public interface IRepository<T> where T : BaseEntity
公共接口i位置,其中T:BaseEntity

我目前使用的是通用存储库(
IRepository
)和自定义存储库(
ICustomRepository
)的混合。不过,我不会从我的存储库中公开
IQueryable
IQueryOver

此外,我只将我的存储库用作查询接口。我通过将会话(工作单元)对象注入到存储库中来执行所有保存、更新和删除操作。这使我能够跨不同的存储库进行事务处理

我发现,我肯定不能从通用存储库中完成所有工作,但它们在许多情况下都非常有用


为了回答您的问题,我认为如果您可以使用单一的通用存储库,那么使用单一的通用存储库并不是一个坏主意。在我的实现中,这不起作用,但如果它对您有效,那就太好了。我认为这取决于什么最适合你。我认为你永远不会找到一个完全适合你的情况的解决方案。我发现混合解决方案最适合我。

我在项目中也做过类似的工作。一个缺点是,您必须小心不要创建selectn+1错误。我通过传递一个单独的属性列表来绕过它

您将听到的反对像这样包装ORM的主要论点是,它是一个泄漏的抽象。您仍然需要编写一些“gotchas”代码,比如selectn+1,您无法充分利用NH的缓存支持(至少没有额外的代码)


在Ayende的博客上有一篇关于这种方法的利弊的文章。他或多或少地反对这种模式,但也有一些相反的观点。

我已经为NHibernate实现了这样的存储库。你可以看到一个例子


在该实现中,您可以进行快速加载和获取。陷阱在于,对于NH,您通常需要能够使用QueryOver或CriteriaAPI来访问数据(不幸的是,LINQ提供程序还远远不够完善)。有了这样一个抽象,它可能会成为一个导致抽象泄漏的问题

我实际上已经脱离了存储库模式,创建了一个工作单元接口——我发现它有局限性

除非您预期数据存储会发生变化,即从数据库到文本文件或XML(我从未遇到过这种情况),否则最好使用ISession。您正试图抽象您的数据访问,这正是NHibernate所做的。使用存储库限制了Fetch()、FetchMany()等非常酷的功能。ISession是您的工作单元


拥抱NHibernate,直接使用ISession

我使用这种方法,但我确实从我的存储库中公开IQueryOver甚至会话,这使我能够允许NHibernate进入我的控制器或助手类。对我来说效果很好。我发现存储库模式使使用存储库的代码更容易进行单元测试。@ColeW-我在测试中使用了sqlite内存数据库。它很快,我不需要在ISession上创建额外的层。我以前使用IRepository,但一旦我切换到ISession,使用NHibernate就容易多了。@ToniParviainen我说的是单元测试。“你所说的是集成测试。”ColeW说。我假设您正在谈论模拟您的db访问并使用存储库来实现这一点?我总是直接处理数据,不管是SQLLite还是SQL。我发现额外的复杂性不起作用,价值和时间总是客户的问题,该死的客户和他们的交付物…@Chev我同意你的说法。我混合了这两种测试。在我的情况下,我发现尝试并执行所有集成测试更加复杂。