我应该返回 IEnumerable吗?或IQueryable来自我的 DAL?

发布于 2024-09-05 19:07:47 字数 844 浏览 4 评论 0原文

我知道这可能是意见,但我正在寻找最佳实践。

据我了解, IQueryable 实现 IEnumerable,因此在我的 DAL 中,我当前具有如下所示的方法签名:

IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByCategory(int cateogoryId);
Product GetProduct(int productId);

我应该使用 IQueryable< ;T> 在这里?

这两种方法的优点和缺点是什么?

请注意,我计划使用存储库模式,因此我将拥有一个如下所示的类:

public class ProductRepository {

    DBDataContext db = new DBDataContext(<!-- connection string -->);

    public IEnumerable<Product> GetProductsNew(int daysOld) {
        return db.GetProducts()
          .Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld ));
    }
}

我应该将 IEnumerable 更改为 IQueryable 吗?其中一方有什么优点/缺点?

I know this could be opinion, but I'm looking for best practices.

As I understand, IQueryable<T> implements IEnumerable<T>, so in my DAL, I currently have method signatures like the following:

IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByCategory(int cateogoryId);
Product GetProduct(int productId);

Should I be using IQueryable<T> here?

What are the pros and cons of either approach?

Note that I am planning on using the Repository pattern so I will have a class like so:

public class ProductRepository {

    DBDataContext db = new DBDataContext(<!-- connection string -->);

    public IEnumerable<Product> GetProductsNew(int daysOld) {
        return db.GetProducts()
          .Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld ));
    }
}

Should I change my IEnumerable<T> to IQueryable<T>? What advantages/disadvantages are there to one or the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

第几種人 2024-09-12 19:07:48

这取决于您想要什么行为。

  • 返回 IList告诉调用者他们已经收到了他们请求的所有数据
  • 返回 IEnumerable告诉调用者他们需要迭代结果,它可能会被延迟加载。
  • 返回 IQueryable告诉调用者结果由可以处理某些类查询的 Linq 提供程序支持,从而将形成高性能查询的负担交给调用者。

虽然后者为调用者提供了很大的灵活性(假设您的存储库完全支持它),但它是最难测试的,并且可以说是最不具有确定性的。

It depends on what behavior you want.

  • Returning an IList<T> tells the caller that they've received all of the data they've requested
  • Returning an IEnumerable<T> tells the caller that they'll need to iterate over the result and it might be lazily loaded.
  • Returning an IQueryable<T> tells the caller that the result is backed by a Linq provider that can handle certain classes of queries, putting the burden on the caller to form a performant query.

While the latter gives the caller a lot of flexibility (assuming your repository fully supports it), it's the hardest to test and, arguably, the least deterministic.

孤芳又自赏 2024-09-12 19:07:48

还有一件事需要考虑:您的分页/排序支持在哪里?如果您在存储库中提供分页支持,则返回 IEnumerable 就可以了。如果您在存储库外部进行分页(例如在控制器或服务层中),那么您确实需要使用 IQueryable,因为您不想在分页之前将整个数据集加载到内存中。

One more thing to think about: where is your paging/sorting support? If you are providing paging support within your repository, returning IEnumerable<T> is fine. If you are paging outside of your repository (like in the controller or service layer) then you really want to use IQueryable<T> because you don't want to load the entire dataset into memory before it's paged.

清眉祭 2024-09-12 19:07:48

HUUUUGGGE 区别。我经常看到这一点。

您可以在 IQueryable 到达数据库之前构建它。 IQueryable 仅在调用急切函数(例如 .ToList())或您实际尝试提取值时才访问数据库。 IQueryable = 懒惰。

IEnumerable 将立即针对数据库执行您的 lambda。 IEnumerable = 渴望。

至于与Repository模式一起使用,相信是很急切的。我通常会看到 IList 被传递,但其他人需要为您解决这个问题。编辑 - 您通常会看到 IEnumerable 而不是 IQueryable,因为您不希望层经过存储库 A) 确定数据库命中何时发生或 B) 在存储库外部的联接中添加任何逻辑

有一个我喜欢的非常好的 LINQ 视频很多——它不仅仅是 IEnumerable v IQueryable,但它确实有一些奇妙的洞察力。

http://channel9.msdn。 com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/

HUUUUGGGE difference. I see this quite a bit.

You build up an IQueryable before it hits the database. The IQueryable only hits the DB once an eager function is called (.ToList() for example) or you actually try to pull values out. IQueryable = lazy.

An IEnumerable will execute your lambda against the DB right away. IEnumerable = eager.

As for which to use with the Repository pattern, I believe it's eager. I usually see ILists being passed but someone else will need to iron that out for you. EDIT - You usually see IEnumerable instead of IQueryable because you don't want layers past your Repository A) determining when the database hit will happen or B) Adding any logic to the joins outside the Repository

There is a very good LINQ video that I enjoy a lot- it hits more than just IEnumerable v IQueryable, but it really has some fantastic insight.

http://channel9.msdn.com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/

音盲 2024-09-12 19:07:48

您可以使用 IQueryable 并接受有人可以创建一个可能发生 SELECT N+1 的场景。这是一个缺点,而且您最终可能会在存储库之上的层中得到特定于存储库实现的代码。这样做的优点是,您允许在存储库外部表达委托的常见操作(例如分页和排序),从而减轻此类担忧。如果您需要将数据与其他数据库表连接起来,它也更加灵活,因为查询将仍然是一个表达式,因此可以在解析为查询并命中数据库之前添加到其中。

另一种方法是锁定您的存储库,以便它通过调用 ToList() 返回具体化列表。以分页和排序为例,您需要将skip、take和排序表达式作为参数传递给存储库的方法,并使用这些参数仅返回结果窗口。这意味着存储库承担分页和排序以及所有数据投影的责任。

这有点需要判断,您是否为您的应用程序提供 linq 的强大功能,并降低存储库的复杂性,或者您是否控制数据访问。对我来说,这取决于与每个实体关联的查询数量、实体组合以及我想要管理这种复杂性的位置。

You can use IQueryable and accept that someone could create a scenario where a SELECT N+1 could happen. This is a disadvantage, along with the fact that you may end up with code that is specific to your repository implementation in the layers above your repository. The advantage of this is that you are allowing the delegation common operations like paging and sorting to be expressed outside of your respository, therefore alleviating it of such concerns. It is also more flexible if you need to join the data with other database tables, as the query will remain an expression, so can be added to before its resolved into a query and hits the database.

The alternative is to lock down your repository so that it returns materialised lists by calling ToList(). With the example of paging and sorting, you will need to pass in skip, take and a sort expression as parameters to the methods of your repository, and use the parameters to return only a window of results. This means that the repository is taking on the responsibility of paging and sorting, and all of the projection of your data.

This is a bit of a judgement call, do you give your application the power of linq, and have less complexity in the repository, or do you control your data access. For me it depends on the number of queries associated with each entity, and combinations of entities, and where I want to manage that complexity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文