Entity Framework高效查询

4
假设我有一个模型,Article,它有大量的列,数据库中包含超过100,000行。如果我执行 var articles = db.Articles.ToList() 这样的操作,它会为每篇文章从数据库中检索整个文章模型,并将其保存在内存中,对吗?
因此,如果我正在填充一个仅显示条目日期和标题的表格,是否有一种方法可以使用实体框架从数据库检索这些列,并且效率更高呢?
根据这里的说法:

跟踪返回对象需要成本。检测对象更改并确保多个请求返回同一逻辑实体的相同对象实例需要将对象附加到ObjectContext实例。如果不计划对对象进行更新或删除,并且不需要标识管理,则在执行查询时考虑使用NoTracking合并选项。

看起来我应该使用 NoTracking,因为数据没有被更改或删除,只是展示而已。因此,我的查询现在变成了 var articles = db.Articles.AsNoTracking().ToList()。还有其他可以使这更有效率的事情要做吗?
另一个问题是,根据这个答案,使用.Contains(...) 在处理大型数据库时会导致性能下降。那么,在大型数据库中搜索条目的推荐方法是什么?

顺便说一句:Contains 不慢是因为数据库表很大。Contains 会问:“给我那些具有 PropertyXValue = 1 或 PropertyXValue = 5 或 PropertyXValue = 7 等等的实体。” 如果你要求的“OR 值”的集合很大,那么 Contains 就会变慢。即使对于一个小表或空表,它也会变慢。 - Slauma
1个回答

4

这被称为投影,在SQL中仅翻译为SELECT column1, column2, ...

var result = db.Articles
    .Select(a => new
    {
        Date = a.Date,
        Title = a.Title
    })
    .ToList();

与其使用a => new { ... }(创建“匿名”对象列表),您也可以使用命名的帮助程序类(或“视图模型”):a => new MyViewModel { ... },其中仅包含所选属性(但您不能将a => new Article { ... }用作实体本身)。

对于这样的投影,您不需要AsNoTracking(),因为投影数据无论如何都不会被跟踪,只有完整的实体对象才会被跟踪。

与其使用Contains,更常见的方法是使用Where,例如:

var date = DateTime.Now.AddYears(-1);
var result = db.Articles
    .Where(a => date <= a.Date)
    .Select(a => new
    {
        Date = a.Date,
        Title = a.Title
    })
    .ToList();

这将仅选择不超过一年的文章。 Where 被翻译成SQL WHERE语句,并在数据库中执行过滤器操作(根据表大小和适当的索引等情况,其速度与SQL查询一样快)。只有此过滤器的结果会被加载到内存中。 编辑 针对您下面的评论:
请不要将IEnumerable<T>.Contains(T t)string.Contains(string subString)混淆。您在问题中链接的答案涉及到Contains的第一版本。如果您想要搜索文本正文中包含字符串"keyword"的文章,则需要使用第二个Contains版本。
string keyword = "Entity Framework";
var result = db.Articles
    .Where(a => a.Body.Contains(keyword))
    .Select(a => new
    {
        Date = a.Date,
        Title = a.Title
    })
    .ToList();

这将在SQL中翻译成类似于WHERE Body like N'%Entity Framework%'的语句。有关Contains性能不佳的答案根本不适用于此版本的Contains

我大多数情况下使用 Where,但是当要查找正文中包含“关键字”的文章时,.Contains 是否是最好的搜索方式?此外,在你的示例中,你有 .Where(a => date <= a.Date),难道不应该是 .Where(a => a.Date >= date) 吗?或者这样做是否重要? - Garrett Fogerlie
@GarrettFogerlie:关于Contains,请看我上面的编辑。但是如果你有很多这样的关键字查询,那么“全文搜索”功能可能是更好的解决方案。对于date <= a.Datea.Date >= date,没有关系,它们会产生相同的结果。 - Slauma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接