Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
2012-04-13 17:36
441 查看
来自博客园开发团队开发前线最新消息:
在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B。通常做法是在LINQ查询中使用Include()。但是,如果你在查询条件中用到了实体B,EF会自动加载实体B,这时Include不仅是多余的,而且还会增加额外的LEFT OUTER JOIN查询,影响性能。
请看我们在博问开发中遭遇这个问题时的一段代码:
在上面的代码中,我们想在GetActiveQuestions()返回List<QuestionItem>时,QuestionItem中要包含User信息,所以在LINQ查询使用了.Include(q => q.User)。
(特别要注意的是:这里把q.User.IsActive作为查询条件之一)
然后我们用SQL Server Profiler发现,Entity Framework生成了如下的SQL语句:
[dbo].[Users]表对应的就是User实体类,上面的SQL中[dbo].[Users]出现了两次JOIN,由于[Users]表数据量比较大,两次JOIN影响了执行计划,查询耗时增加。这显然是要避免的。
在与这个问题一阵激战之后,我们终于找到解决方法 —— 去掉Include,就这么简单!
从这个地方看,Entity Framework还是挺聪明的,但是由于不知道它的这个聪明之处,反而带来了问题。
所以,代码如人,要和她相处好,就要了解她的一切!
在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B。通常做法是在LINQ查询中使用Include()。但是,如果你在查询条件中用到了实体B,EF会自动加载实体B,这时Include不仅是多余的,而且还会增加额外的LEFT OUTER JOIN查询,影响性能。
请看我们在博问开发中遭遇这个问题时的一段代码:
//For q.cnblogs.com public class QuestionService { private IRepository<QuestionItem> _questionRepository; public QuestionService(IUnitOfWork unitOfWork) : base(unitOfWork) { _questionRepository = new Repository<QuestionItem>(unitOfWork); } public List<QuestionItem> GetUnsolvedQuestions(int pageIndex, int pageSize) { return _questionRepository.Entities .Include(q => q.User) .Where(q => q.IsActive && q.User.IsActive) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .ToList(); } } public class QuestionItem { public int Id { get;set; } public string Title { get; set; } public bool IsActive { get; set; } public int UserId { get; set; } public User User { get; set; } } public class User { public int UserId { get; set; } public bool IsActive {get;set;} }
在上面的代码中,我们想在GetActiveQuestions()返回List<QuestionItem>时,QuestionItem中要包含User信息,所以在LINQ查询使用了.Include(q => q.User)。
(特别要注意的是:这里把q.User.IsActive作为查询条件之一)
然后我们用SQL Server Profiler发现,Entity Framework生成了如下的SQL语句:
SELECT TOP (25) [Filter1].[Id] AS [Id], [Filter1].[Title] AS [Title], [Filter1].[UserId] AS [UserId], [Filter1].[UserId1] AS [UserId1], [Filter1].[IsActive1] AS [IsActive], [Filter1].[UserId2] AS [UserId1], [Filter1].[IsActive2] AS [IsActive1] FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Title] AS [Title], [Extent1].[UserId] AS [UserId1],[Extent1].[IsActive] AS [IsActive1], [Extent3].[UserID] AS [UserID2], [Extent3].[IsActive] AS [IsActive2], row_number() OVER (ORDER BY [Extent1].[QID] DESC) AS [row_number] FROM [dbo].[question_Item] AS [Extent1] INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserID] = [Extent2].[UserID] LEFT OUTER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[UserID] = [Extent3].[UserID] WHERE ([Extent1].[IsActive] = 1) AND ([Extent2].[IsActive] = 1) ) AS [Filter1] WHERE [Filter1].[row_number] > 0 ORDER BY [Filter1].[Id] DESC
[dbo].[Users]表对应的就是User实体类,上面的SQL中[dbo].[Users]出现了两次JOIN,由于[Users]表数据量比较大,两次JOIN影响了执行计划,查询耗时增加。这显然是要避免的。
在与这个问题一阵激战之后,我们终于找到解决方法 —— 去掉Include,就这么简单!
从这个地方看,Entity Framework还是挺聪明的,但是由于不知道它的这个聪明之处,反而带来了问题。
所以,代码如人,要和她相处好,就要了解她的一切!
相关文章推荐
- Linq使用Group By分析 Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
- Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
- Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
- Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
- 《Entity Framework 6 Recipes》中文翻译系列 (26) ------ 第五章 加载实体和导航属性之延缓加载关联实体和在别的LINQ查询操作中使用Include()方法
- oracle 开窗函数的使用,表的外关联,子查询的封装以及where使用的注意事项
- mongodb_查询操作使用_条件查询、where子句等
- Oracle使用like时要注意空条件的情况,请尽量使用以下语句(对含逗号或特定符号的查询)
- 关于C#中关于List.where中过滤条件的使用注意事项
- union all 和where条件一起使用查询数据不对的问题
- SQL 两表关联查询 where 条件中等号两端字段顺序对效率的影响
- And,Where使用提示以及用+进行左关联的提示及注意事项
- And,Where使用提示以及用+进行左关联的提示及注意事项
- 在ASP中使用SQL语句之2:用WHERE子句设置查询条件
- Hibernate使用sql语句查询,返回实体类型的方法及注意事项
- 关于C#中关于List.where中过滤条件的使用注意事项--笔记
- 使用hql或条件查询解决一对多关联查询的N+1查询问题
- LinqDataSource.Where中如何使用Contains查询包含双引号(")的条件
- 使用ADF-BC 实现查询功能之四:通过代码动态设置Where条件参数
- 时间类型数据使用between ...and ..语句条件查询时应注意的问题