通用存储库扩展:继承与扩展方法

时间:2014-01-24 15:01:50

标签: c# entity-framework inheritance extension-methods repository-pattern

我打算在我的实体框架项目中使用Generic Repository。但这对于扩展基础通用存储库不包含的操作的存储库更好。

继承:

public class CustomerRepository:Repository<Customer>
{
    public decimal GetCustomerOrderTotalByYear(int customerId, int year)
    {
        return base
            .FindById(customerId)
            .Orders.SelectMany(o => o.OrderDetails)
            .Select(o => o.Quantity*o.UnitPrice).Sum();
    }
}

扩展方法:

public static class CustomerRepositoryExtensions
{
    public static decimal GetCustomerOrderTotalByYear(this Repository<Customer> customerRepository, int customerId, int year)
    {
        return customerRepository
            .FindById(customerId)
            .Orders.SelectMany(o => o.OrderDetails)
            .Select(o => o.Quantity*o.UnitPrice).Sum();
    }
}

4 个答案:

答案 0 :(得分:4)

不要在存储库上创建查询方法。使用存储库来维护聚合一致性而不是通用查询。否则,您的界面非常臃肿,您的存储库最终会成为无数不同查询的倾销场。只需创建查询和查询处理程序。我只使用存储库来获取我要更新的数据。

执行this之类的操作。

这是一种更为SOLID的方法。

答案 1 :(得分:0)

我会继承。

在我看来,扩展方法适用于你想要为你无法控制的类添加功能(例如字符串扩展),或者当你想为一个接口提供功能时,无论是否应该做同样的事情您当前正在使用的实现(例如,LINQ是IEnumerable的一组扩展)

在这种情况下,有意义的是说“这是我的CustomerRepository,而且CustomerRepository有一些额外的东西,或者做了一些与默认行为略有不同的东西,但在一天结束时,客户存储库一个存储库。

请注意,这完全是主观的,并且基于个人偏好,但我的投票是继承路线。

答案 2 :(得分:0)

我通常走了继承路线。这看起来非常类似于你所说的。我有一个Generic&#34; base&#34;注入IUnitOfWork的存储库实现。然后在我的每个BaseRepository继承类中,我将实现我的查询。这是我用旧版本的#34;模式制作的旧帖子&#34;:https://stackoverflow.com/a/18788895/1426342

这种方法对我来说似乎总是最直接的,并且当我切换代码时更容易向我的客户解释。从前到后遵循执行路径更容易。然而,对于较大的系统,它会变得非常混乱!它还将您的上下文实现耦合到您的存储库。我已经做了一些额外的事情来传递上下文类型作为一个通用的帮助,并允许我有多个上下文实现,我可以发布,如果你喜欢。

最近,受到同事的挑战,要进一步细分并将Entity Framework与我的存储库实现分离,我尝试了你发布的第二种方法。说实话,我想我可能更喜欢这种方法。它似乎对我来说更轻,因为你没有注入所有那些不同的&#34;存储库&#34;诚实地甚至不需要注射的方法。看看这个人的博客,找到这个实现的一个很好的例子:http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc

仔细研究后,我认为你会同意。扩展方法是一种更高效的解决方案。

答案 3 :(得分:0)

旧文章,但是我想在扩展名更合适时添加一点-当您通过DI容器解决依赖项并且您有{em>很多 Repositories时。在这种情况下,您只需要注册您的通用仓库,而不必分别注册每个仓库。