4

假设我有一个模型,Article它有大量的列并且数据库包含超过 100,000 行。如果我做类似var articles = db.Articles.ToList()的事情是为数据库中的每篇文章检索整个文章模型并将其保存在内存中,对吗?

因此,如果我正在填充一个仅显示条目日期及其标题的表,是否有办法使用实体框架仅从数据库中检索这些列,它会更有效吗?

据此,_

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

看起来我应该使用NoTracking,因为数据没有被更改或删除,只显示。所以我的查询现在变成了var articles = db.Articles.AsNoTracking().ToList(). 我还应该做其他事情来提高效率吗?

我的另一个问题是,根据这个答案.Contains(...),在处理大型数据库时使用会导致性能大幅下降。用于搜索大型数据库中的条目的推荐方法是什么?

4

1 回答 1

4

它被称为投影,只是转换为SELECT column1, column2, ...SQL 中的 a:

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

除了a => new { ... }(创建“匿名”对象的列表)之外,您还可以使用命名的助手类(或“视图模型”):a => new MyViewModel { ... }它仅包含选定的属性(但您不能将a => new Article { ... }其用作实体本身)。

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

而不是使用Contains更常见的方法是使用Wherelike:

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只是被翻译成一条 SQLWHERE语句并在数据库中执行过滤器(这与 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();

这将转化为类似于WHERE Body like N'%Entity Framework%'SQL 的内容。关于性能不佳的答案Contains根本不适用于这个版本Contains

于 2012-07-21T12:17:50.147 回答