创建存储库而不使用IQueryable进行规范

时间:2011-03-24 10:42:13

标签: c# repository iqueryable

我最近一直在研究DDD,存储库和规范模式,在阅读完整篇博客和示例之后,我试着想出一个我很满意的存储库。

我对此很陌生,所以仍然试图把握与我无关的概念。我一直在我的存储库中暴露IQueryable直到最近,但是在理解了IQueryable是一个漏洞抽象之后因为它是延迟执行并且有效地从我的数据层跨越边界我改变了它以便我的存储库返回IEnumerable而不是。

所以我可能会举例如下: -

public interface IUserRepository
{
    IEnumerable<User> All();

    void Save(User item);
    void Delete(User item);
}

我认为这似乎不错,但如果我想过滤数据我的名字或电子邮件怎么办?在阅读博客文章后,我实现了一种将ICriteria传递给All()方法的方法。

public IEnumerable<TEntity> All(ICriteria<TEntity> criteria)
{
    return criteria.BuildQueryFrom(Set).ToList();
    // Set is a DbSet from EntityFramework
}

示例标准类: -

public class AccountById : ICriteria<Account>
{
    private readonly int _id;

    public AccountById(int id)
    {
        _id = id;
    }

    IQueryable<Account> ICriteria<Account>.BuildQueryFrom(DbSet<Account> dbSet)
    {
        return from entity in dbSet
               where entity.Id == _id
               select entity;
    }
}

这很好用,我可以建立这些标准类来满足我的要求并将它们传递到回购中,一切运作良好。

我不喜欢的一件事就是与IQueryable绑定,因为我必须使用支持Linq的ORM,所以如果我想在我的存储库中使用SqlCommand来表示性能,那么我可以编写更清晰的SQL而不是ORM生成了SQL,我该怎么做呢?

我还想避免为FindById,FindByUsername,FindByEmail等每个过滤器编写一个新方法。

所以基本上我将如何创建一个存储库,允许我指定我想要选择的标准而不使用IQueryable,所以无论我使用EF,nHibernate还是普通的SqlCommand,它仍然可以工作?我正在寻找一个使用SqlCommand和规范模式的例子。

在ORM之前,人们过去常常这样做过吗?

提前致谢,希望有人能告诉我光明! :)

1 个答案:

答案 0 :(得分:0)

就个人而言,我不介意IQueryable是一个漏洞抽象,因为它允许我在我的服务层编写LINQ查询,因此有更多可测试的代码。只要实现IQueryable的对象保留在服务层内(即不将它们返回到表示层),我就不会发现问题。它最大限度地提高了应用程序的可测试性。例如,请参阅my blog post about testable LINQified repositories