首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何强迫实体框架在可空外键上生成SQL内部连接?

如何强迫实体框架在可空外键上生成SQL内部连接?
EN

Stack Overflow用户
提问于 2017-06-26 04:26:56
回答 3查看 1.1K关注 0票数 1

更新: EF团队的UserVoice站点上有关于这方面的请求。投赞成票

关于Include语句的这个线程也是相关的。

为什么这很重要

查询EF6和Linq!但是,如果它涉及几个联接表和一个可为空的外键,那么它就会陷入1000行T的泥潭。

如果内部连接被强制执行,它将只执行10行

(例如,),EF6项目引用一个SQL数据库。有一张学生桌和一张辅导桌。不是每个学生都有导师,所以Student.TutorId可以是空的。

所有学生辅导信息很容易在Tutor:中找到

代码语言:javascript
复制
SELECT s.Name, t.Name FROM Student s JOIN Tutor t ON s.TutorId = t.Id

Linq是这样的:

代码语言:javascript
复制
var result = context.Students
.Where(s => s.TutorId != null)
.Select(s => new { StudentName = s.Name, TutorName = s.Tutor.Name })
.ToList();

但是EF6生成这个SQL:

代码语言:javascript
复制
SELECT [Extent1].[Name], 
    CASE WHEN ([Extent2].[FirstName] IS NULL)
       THEN N'' 
    ELSE
       [Extent2].[Name] 
    END AS [C1]
FROM  [dbo].[Student] AS [Extent1]
LEFT OUTER JOIN [dbo].[Tutor] AS [Extent2] ON [Extent1].[TutorId] = [Extent2].[Id]
WHERE [Extent1].[TutorId] IS NOT NULL

感谢彼得在很多年前为追问做了这件事。希望现在有一个比放弃Linq更好的答案。

这个GitHub仓库有用于实验的源代码。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-06-26 10:29:24

唯一可靠的方法是,如果您能够以这样的方式构造LINQ查询,即通过SelectMany“导航”从所需的端到可选端的关系,我猜这使得它不一般适用。

为了演示起见,如果您编写的示例查询如下

代码语言:javascript
复制
var result = db.Tutors
    .SelectMany(t => t.Students, (t, s) => new { StudentName = s.Name, TutorName = t.Name })
    .ToList();

生成的SQL如下所示

代码语言:javascript
复制
SELECT
    [Extent1].[Id] AS [Id],
    [Extent2].[Name] AS [Name],
    [Extent1].[Name] AS [Name1]
    FROM  [dbo].[Tutors] AS [Extent1]
    INNER JOIN [dbo].[Students] AS [Extent2] ON [Extent1].[Id] = [Extent2].[TutorId]
票数 2
EN

Stack Overflow用户

发布于 2017-06-26 07:04:48

如果在投影后添加非空条件,实体框架将生成内部连接:

代码语言:javascript
复制
var result = context.Students
.Select(s => new { StudentName = s.Name, TutorName = s.Tutor.Name })
.Where(x => x.TutorName != null)
.ToList();

我不知道为什么会这样。如果EF足够聪明地推断出x.TutorName != null相当于一个内部连接,我认为它应该能够与s.TutorId != null一样。

票数 3
EN

Stack Overflow用户

发布于 2017-06-26 06:01:20

在这种情况下,您应该显式地加入表,而不是将家教称为学生的属性:

代码语言:javascript
复制
var result = (from s in context.Students
             join t in context.Tutors
             on s.TutorId equals t.Id
             select new 
             {
                 StudentName = s.Name, 
                 TutorName = t.Name
             }).ToLost();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44753108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档