假设我有一个模型,Article
有大量列,数据库包含超过100,000行。如果我执行var articles = db.Articles.ToList()
之类的操作,它会检索数据库中每篇文章的整个文章模型并将其保存在内存中吗?
因此,如果我填充的表格只显示条目的日期,那么它的标题是仅使用实体框架从数据库中检索这些列的方法,并且它是效率更高?
根据this,
跟踪对象中的返回对象需要一定的成本 上下文。检测对象的更改并确保多个 对同一逻辑实体的请求返回相同的对象实例 要求将对象附加到ObjectContext实例。如果你 不打算对对象进行更新或删除,也不要求 身份管理,考虑使用NoTracking合并选项时 你执行查询。
看起来我应该使用NoTracking
,因为数据没有被更改或删除,只显示。所以我的查询现在变为var articles = db.Articles.AsNoTracking().ToList()
。我还应该做些什么来提高效率吗?
我的另一个问题是,根据this answer,使用.Contains(...)
会在处理大型数据库时导致性能下降。搜索大型数据库中的条目的推荐方法是什么?
答案 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
。