0

次のデータモデルがあります。

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; } 
}

IQueryableforを考え出そうとしていますが、Licenses テーブルから選択したプロパティCompletedCoursesを入力CompletedCourse.LicenseNumberして、完了したコース レコードと一致させたいと考えています。LicenseNumberFirstOrDefault()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);

これは単一のクエリで実行できるものですか? 前もって感謝します。

4

2 に答える 2

7

これを行う方法は次のとおりです。

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 });

ただし、このタイプのプロジェクションでは、クエリに s を使用できないことに注意してIncludeください (使用できますが、有効にはなりません)。

上記から取得している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]

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 });
于 2016-03-15T20:16:05.347 に答える
0

@IvanStoevの回答は、匿名型に参加するのに非常に役立ちましたが、インクルードが必要だったため、最終的には使用できませんでした。これは私が行った解決策であり、私の状況では1つではなく2つのDBクエリになります。

var entries = context.CompletedCourses
    .Include(x => x.Agent)
    .Include(x => x.Course);
var courses = entries.ToList();
var courseIds = entries.Select(x => x.CompletedCourseId);
var licenses =
    (from course in entries
        join license in context.Licenses
        on new { course.AgentId, course.Course.StateId } 
        equals new { AgentId = license.UserId, license.StateId }
        where courseIds.Contains(course.CompletedCourseId)
        select license);
foreach (var course in courses)
{
    var license = agentLicenses.FirstOrDefault(x => x.UserId == course.AgentId && 
        x.StateId == course.Course.StateId);
    if (license != null)
    {
        course.LicenseNumber = license.LicenseNumber;
    }
}
return courses;
于 2016-03-16T15:05:37.240 に答える