gpt4 book ai didi

c# - 我的 Entity Framework 存储库和服务层方法应返回哪些类型的 : List, IEnumerable、IQueryable?

转载 作者:太空狗 更新时间:2023-10-29 17:33:29 25 4
gpt4 key购买 nike

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

public class Repository
{
private AppDbContext context;

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


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

然后我的服务层可以根据需要为其他方法(where、分页等)执行 LINQ

现在我的服务层设置为返回 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;
}

这意味着在我的代码隐藏中,如果我想绑定(bind)到转发器或其他控件,我必须执行 ToList()。

这是处理返回类型的最佳方法,还是我需要在从服务层方法返回之前转换为列表?

最佳答案

这两种方法都是可行的,只是选择问题。

一旦您使用了IQueryable,您就拥有了在大多数情况下都能正常工作的简单存储库,但它的可测试性更差,因为在IQueryable 上定义的查询是linq-to-entities。如果你模拟存储库,它们在单元测试中是 linq-to-objects = 你不测试你的真实实现。您需要集成测试来测试您的查询逻辑。

一旦您使用IEnumerable,您将拥有非常复杂的存储库公共(public)接口(interface) - 您将需要为每个需要在存储库上公开的特殊查询的实体提供特殊的存储库类型。这种存储库在存储过程中更为常见——存储库中的每个方法都映射到单个存储过程。这种类型的存储库提供了更好的关注点分离和更少的抽象泄漏,但同时它消除了很多 ORM 和 Linq 灵 active 。

对于最后一种方法,您可以使用组合方法,其中您有方法返回 IEnumerable 用于最常见的场景(更频繁地使用查询)和一种方法公开 IQueryable 用于罕见或复杂的动态构建查询。

编辑:

如注释中所述,使用 IQueryable 有一些副作用。当您公开 IQueryable 时,您必须在执行查询之前保持上下文事件 - IQueryable 使用与 IEnumerable 相同的方式延迟执行,因此除非您调用 ToListFirst 或其他执行查询的函数,您仍然需要您的上下文。

实现这一目标的最简单方法是在存储库中使用一次性模式 - 在其构造函数中创建上下文并在存储库处理时处理它。然后您可以使用 using block 并在其中执行查询。这种方法适用于非常简单的场景,您对每个存储库的单个上下文感到满意。更复杂(和常见)的场景需要在多个存储库之间共享上下文。在这种情况下,您可以使用诸如上下文提供者/工厂(一次性)之类的东西并将工厂注入(inject)存储库构造函数(或允许提供者创建存储库)。这导致 DAL 层工厂和自定义工作单元。

关于c# - 我的 Entity Framework 存储库和服务层方法应返回哪些类型的 : List, IEnumerable、IQueryable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6416506/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com