哪些类型应我的实体框架库和服务层方法返回:列表中,IEnumerable的,IQueryable的? [英] Which types should my Entity Framework repository and service layer methods return: List, IEnumerable, IQueryable?

查看:273
本文介绍了哪些类型应我的实体框架库和服务层方法返回:列表中,IEnumerable的,IQueryable的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个返回实体的IQueryable的一个具体的存储库实现:

I have a concrete repository implementation that returns a IQueryable of the entity:

public class Repository
{
    private AppDbContext context;

    public Repository()
    {
        context = new AppDbContext();
    }


    public IQueryable<Post> GetPosts()
    {
        return context.Posts;
    }
}

根据需要其他的方法(其中,分页等)

My service layer can then perform LINQ as needed for other methods (where, paging, etc)

现在我的服务层是设置返回的IEnumerable

Right now my service layer is setup to return IEnumerable:

public IEnumerable<Post> GetPageOfPosts(int pageNumber, int pageSize)
{ 
    Repository postRepo = new Repository();

    var posts = (from p in postRepo.GetPosts()  //this is IQueryable
                orderby p.PostDate descending
                select p)
                .Skip((pageNumber - 1) * pageSize)
                .Take(pageSize);

    return posts;
}

这意味着在我的codebehind我必须做一个了ToList(),如果我要绑定到中继器或其他控制。

This means in my codebehind I have to do a ToList() if I want to bind to a repeater or other control.

这是处理的返回类型或是否需要进行转换,列出之前,我从我的服务层方法返回的最佳方式?

Is this the best way to handle the return types or do I need to be converting to list before I return from my service layer methods?

推荐答案

这两种方法都是可能的,这是唯一的选择的问题。

Both approaches are possible and it is only matter of choice.

一旦你开始使用的IQueryable 你有简单的存储库将在大多数情况下工作,但它更糟糕的是可检验的,因为在的IQueryable 是LINQ到实体。如果模拟库他们LINQ到对象的单元测试=你不测试你的真正实施。您需要集成测试来测试你的查询逻辑。

Once you use IQueryable you have simple repository which will work in the most cases but it is worse testable because queries defined on IQueryable are linq-to-entities. If you mock repository they are linq-to-objects in unit tests = you don't test your real implementation. You need integration tests to test your query logic.

一旦你开始使用的IEnumerable 你有你自己的仓库非常复杂的公共接口 - 你需要特殊的库类型,需要暴露在库特殊查询每一个实体。这种存储库是用存储过程更为常见 - 在库中的每个方法映射到单一的存储过程。这种类型的存储库中提供的顾虑,减少漏抽象更好的分离,但在同一时间,它消除了大量的ORM和LINQ灵活性。

Once you use IEnumerable you will have very complex public interfaces of your repositories - you will need special repository type for every entity which needs special query exposed on the repository. This kind of repositories was more common with stored procedures - each method on the repository was mapped to single stored procedure. This type of repository provides better separation of concerns and less leaky abstraction but in the same time it removes a lot of ORM and Linq flexibility.

在过去,你可以有相结合的办法,你必须返回IEnumerable的为最常见的情况(应用较多查询)的方法之一方法曝光的IQueryable 罕见或复杂的动态建立查询。

For the last you can have combined approach where you have methods returning IEnumerable for most common scenarios (queries used more often) and one method exposing IQueryable for rare or complex dynamically build queries.

编辑:

与使用的IQueryable 有一定的副作用在评论中指出的。当你暴露的IQueryable 你必须保持你的背景下活到执行查询 - 的IQueryable 以同样的方式使用延迟执行为的IEnumerable 所以,除非你叫了ToList 首先或其他执行查询的功能,你仍然需要上下文活着。

As noted in comments using IQueryable has some side effects. When you expose IQueryable you must keep your context alive until you execute the query - IQueryable uses deferred execution in the same way as IEnumerable so unless you call ToList, First or other functions executing your query you still need your context alive.

要实现这一目标最简单的方法是在仓库中使用一次性模式 - 建立在其构造背景和资源库时处置处置它。然后你可以使用块中使用并执行它们内部查询。这种方法是,你很高兴,每个库一个上下文很简单的场景。更复杂的(共同)方案要求范围内多个存储库之间共享。在这种情况下,你可以使用类似语境提供商/工厂(一次性),并注入工厂存储库的构造函数(或允许供应商建立资料库)。这导致DAL层的工厂和工作的自定义单位。

The simplest way to achieve that is using disposable pattern in the repository - create context in its constructor and dispose it when repository disposes. Then you can use using blocks and execute queries inside them. This approach is for very simple scenarios where you are happy with single context per repository. More complex (and common) scenarios require context to be shared among multiple repositories. In such case you can use something like context provider / factory (disposable) and inject the factory to repository constructor (or allow provider to create repositories). This leads to DAL layer factory and custom unit of work.

这篇关于哪些类型应我的实体框架库和服务层方法返回:列表中,IEnumerable的,IQueryable的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆