0

In our EF implementation for Brand New Project, we have GetAll method in Repository. But, as our Application Grows, we are going to have let's say 5000 Products, Getting All the way it is, would be Performance Problem. Wouldn't it ?

if So, what is good implementation to tackle this future problem?

Any help will be hightly appreciated.

4

4 回答 4

3

如果 get all 对集合进行枚举,则可能会成为性能问题,从而导致整个数据集以IEnumerable. 这一切都取决于连接的数量、数据集的大小、是否启用了延迟加载、SQL Server 的执行方式等等。

有些人会说这是不希望的,您可以GetAll()返回一个IQueryable将查询推迟到某些事情导致通过转到 SQL 来填充集合的情况。这样,您可以使用其他Where(), Take(), Skip(), etc 语句过滤结果以允许分页,而无需从数据库中检索所有 5000 多种产品。

于 2013-05-13T20:59:13.153 回答
1

这取决于您的存储库类的设置方式。如果您立即执行查询,即如果您的GetAll()方法返回类似IEnumerable<T>orIList<T>的内容,那么是的,这很容易成为性能问题,除非您真的想一次加载所有记录,否则您通常应该避免这种事情。

另一方面,如果您的GetAll()方法返回一个IQueryable<T>,那么可能根本没有问题,这取决于您是否信任编写查询的人。返回 anIQueryable<T>将允许调用者在实际生成 SQL 代码之前进一步细化搜索条件。就性能而言,只有在使用您的代码的开发人员在执行查询之前没有应用任何过滤器时才会出现问题。如果您足够信任他们,可以给他们足够的绳索让他们上吊(并且可能会降低您的数据库性能),那么仅仅返回IQueryable<T>可能就足够了。

如果您不信任它们,那么正如其他人指出的那样,您可以通过使用Skip()Take()扩展方法来限制查询返回的记录数来实现简单的分页,但请注意,记录可能会漏掉如果人们在您进入下一页之前对数据库进行了更改。使分页与不断变化的数据库无缝工作比很多人想象的要困难得多。

另一种方法是将您的GetAll()方法替换为需要调用者在返回结果之前应用过滤器的方法:

public IQueryable<T> GetMatching<T>(Expression<Func<T, bool>> filter)
{
  // Replace myQuery with Context.Set<T>() or whatever you're using for data access
  return myQuery.Where(filter);
}

然后像var results = GetMatching(x => x.Name == "foo");, 或任何你想做的事情一样使用它。请注意,这可以通过调用轻松绕过GetMatching(x => true),但至少它使意图明确。您还可以将其与第一种方法结合起来,对返回的记录数量设置一个固定上限。

不过,我个人的感觉是,所有这些限制查询的方法只是防止糟糕的开发人员接触你的应用程序,如果你的项目中有糟糕的开发人员,他们无论如何都会找到导致问题的方法你试图做什么。所以我的投票是只返回一个IQueryable<T>并相信它将被负责任地使用。如果人们滥用它,请拿走该方法并为他们提供类似或类似GetAll()的训练轮方法,其中查询逻辑超出了他们的控制范围。GetRecentPosts(int count)GetPostsWithTag(string tag, int count)

于 2013-05-13T21:42:54.553 回答
0

您所指的内容称为分页,通过Skip / Take方法使用 LINQ 非常简单。

EF 查询是延迟加载的,这意味着它们在评估之前不会真正命中数据库,因此以下只会在跳过前 10 行后提取前 10 行

context.Table.Skip(10).Take(10);
于 2013-05-13T20:58:54.577 回答
0

改善这一点的一种方法是使用分页

context.Products.Skip(n).Take(m);
于 2013-05-13T20:59:39.663 回答