实体框架高效查询

时间:2012-07-21 12:06:08

标签: sql-server entity-framework linq-to-sql

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

因此,如果我填充的表格只显示条目的日期,那么它的标题是使用实体框架从数据库中检索这些列的方法,并且它是效率更高?

根据this

  

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

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

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

1 个答案:

答案 0 :(得分: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