在我们的品牌新项目的EF实现中,我们在Repository中有GetAll方法。但是,随着我们的应用程序的增长,我们将有5000个产品,得到它的所有方式,将是性能问题。不是吗?
如果是这样的话,有什么好的实现来解决这个未来的问题?
任何帮助都将受到高度的感谢。
发布于 2013-05-14 05:42:55
这取决于存储库类是如何设置的。如果您立即执行查询,例如,如果您的GetAll()方法返回IEnumerable<T>或IList<T>之类的内容,那么是的,这很容易成为性能问题,您通常应该避免这种事情,除非您真的想一次加载所有记录。
另一方面,如果您的GetAll()方法返回一个IQueryable<T>,那么可能根本没有问题,这取决于您是否信任编写查询的人。返回IQueryable<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-14 04:59:13
如果在集合上枚举get all,则可能会出现性能问题,从而导致在IEnumerable中返回整个数据集。这一切都取决于连接的数量,数据集的大小,如果您启用了延迟加载,SQL Server的性能如何,仅举几个例子。
有些人会说这不是我们想要的,你可以让GetAll()返回一个IQueryable,它会推迟查询,直到某些原因导致集合被填充。这样,您就可以使用其他Where()、Take()、Skip()等语句过滤结果,从而无需从数据库中检索所有5000+产品即可进行分页。
发布于 2013-05-14 04:58:55
您所指的就是所谓的分页,通过Skip/Take方法使用LINQ来做这件事非常简单。
EF查询是延迟加载的,这意味着它们不会实际命中数据库,直到它们被评估,所以下面的语句将只提取跳过前10行之后的前10行
context.Table.Skip(10).Take(10);https://stackoverflow.com/questions/16530959
复制相似问题