具有第一个或默认连接的Linq查询

im1*_*ike 0 c# linq entity-framework linq-query-syntax

我有以下数据模型:

public class Course
{
    public int CourseId { get; set; }
    public int StateId { get; set; }
}

public class CompletedCourse
{
    public int CompletedCourseId { get; set; }
    public int UserId { get; set; }
    public Course Course { get; set; }
    public string LicenseNumber { get; set; }
}

public class License
{
    public int LicenseId { get; set; }
    public int UserId { get; set; }
    public int StateId { get; set; }
    public string LicenseNumber { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

我试图想出一个IQueryableCompletedCourses,我想填充CompletedCourse.LicenseNumberLicenseNumber的物业FirstOrDefault()选择从我的许可证表,其中UserIdStateId配合完成病程记录.

这是我的查询,但我认为这不会正确处理重复的许可证:

var entries =
    (from course in context.CompletedCourses
         join license in context.Licenses on course.UserId equals license.UserId
         where license.StateId == course.Course.StateId
         select course)
    .Include(x => x.Agent)
    .Include(x => x.Course.State);
Run Code Online (Sandbox Code Playgroud)

这可以在一个查询中完成吗?提前致谢.

Iva*_*oev 5

以下是如何做到这一点:

var entries =
    (from course in context.CompletedCourses
     join license in context.Licenses
     on new { course.UserId, course.Course.StateId }
     equals new { license.UserId, license.StateId }
     into licenses
     let licenseNumber = licenses.Select(license => license.LicenseNumber).FirstOrDefault()
     select new { course, licenseNumber });
Run Code Online (Sandbox Code Playgroud)

但请注意,对于这种类型的投影,您不能Include在查询中使用s(您可以,但它们不会生效).

我从上面得到的EF生成的查询是:

SELECT 
    [Extent1].[CompletedCourseId] AS [CompletedCourseId], 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[LicenseNumber] AS [LicenseNumber], 
    [Extent1].[Course_CourseId] AS [Course_CourseId], 
    (SELECT TOP (1) 
        [Extent2].[LicenseNumber] AS [LicenseNumber]
        FROM  [dbo].[Licenses] AS [Extent2]
        INNER JOIN [dbo].[Courses] AS [Extent3] ON [Extent3].[StateId] = [Extent2].[StateId]
        WHERE ([Extent1].[Course_CourseId] = [Extent3].[CourseId]) AND ([Extent1].[UserId] = [Extent2].[UserId])) AS [C1]
    FROM [dbo].[CompletedCourses] AS [Extent1]
Run Code Online (Sandbox Code Playgroud)

可以注意到EF有效地忽略了join,因此通过简单的自然查询可以获得相同的结果:

var entries =
    (from course in db.CompletedCourses
     let licenseNumber =
        (from license in db.Licenses
         where license.UserId == course.UserId && license.StateId == course.Course.StateId
         select license.LicenseNumber).FirstOrDefault()
     select new { course, licenseNumber });
Run Code Online (Sandbox Code Playgroud)