单一存储库与通用方法...坏主意?

时间:2012-02-21 18:32:27

标签: 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 : 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;
}

这样我就可以将一个存储库注入一个类并使用它来获取我需要的任何东西。

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

这似乎对我有用 - 我在这个存储库中定义的方法可以完成我需要的所有工作。但是在我的所有网络搜索中,我都没有找到其他人使用这种方法,这让我觉得我错过了一些东西......这会在我增加应用程序时给我带来问题吗?

我读了很多人谈论每个根实体都有一个存储库 - 但是如果我用一些接口识别根实体并将泛型方法限制为只允许实现该接口的类,那么我是不是实现了同样的东西?

提前感谢任何产品。

5 个答案:

答案 0 :(得分:4)

我目前正在混合使用通用存储库(IRepository<T>)和自定义存储库(ICustomRepository)。我不会在我的存储库中公开IQueryableIQueryOver

此外,我只使用我的存储库作为查询接口。我通过我注入到我的存储库中的Session(工作单元)对象执行所有保存,更新和删除操作。这允许我跨不同的存储库进行交易。

我发现我绝对不能从通用存储库中做任何事情,但它们在许多情况下肯定是有用的。

回答你的问题虽然我不认为拥有一个通用的存储库是一个坏主意,如果你可以使用它。在我的实现中,这不起作用,但如果它适合你,那么这很好。我认为这取决于什么最适合你。我不认为你会找到适合你情况的解决方案。我发现混合解决方案最适合我。

答案 1 :(得分:3)

我在我的项目中做了类似的事情。一个缺点是你必须要小心,不要创建一个选择n + 1错误。我通过传递一个单独的属性列表来急切地获取它。

你要听到的反对包装你的ORM的主要论点是它是一个漏洞的抽象。你仍然需要编写一些像“选择n + 1”这样的“陷阱”的代码,而你却无法充分利用NH的缓存支持(至少没有额外的代码)。

这是关于Ayende博客上这种方法的利弊的good thread。他或多或少地反对这种模式,但也存在一些反驳论点。

答案 2 :(得分:2)

我已经为NHibernate实现了这种类型的存储库。您可以看到示例here

在该实现中,您可以进行急切的加载和获取。缺点是使用NH时,您通常需要能够使用QueryOver或Criteria API来访问数据(遗憾的是LINQ提供程序仍然远非完美)。有了这样的抽象,它可能成为导致漏洞抽象的问题。

答案 3 :(得分:2)

我实际上已经远离了存储库模式并创建了工作单元接口 - 我觉得它有限制。

除非您预期数据存储区发生更改,即从数据库更改为文本文件或XML - 这对我来说从未如此,您最好使用ISession。您正在尝试抽象数据访问,这正是NHibernate所做的。使用存储库限制非常酷的功能,如Fetch(),FetchMany()等等.ISession是您的工作单元。

拥抱NHibernate并直接使用ISession!

答案 4 :(得分:0)

我在一些项目上成功使用了这种方法。每个BaseEntity的许多IRepository<T>传递到我的服务层会很麻烦,但它确实有效。我要改变的一件事是将where T :放在界面而不是方法

public interface IRepository<T> where T : BaseEntity