Sunting
Pengujian di bawah ini dilakukan dengan SQL Server dan SqlClient
sebagai penyedia. Fakta bahwa masalah tidak dapat direproduksi dengan SQL Server menimbulkan pertanyaan apakah MySql
penyedia yang Anda gunakan memiliki bug yang membuat SQL yang salah untuk kueri LINQ Anda. Sepertinya masalah yang sama seperti di pertanyaan ini
di mana masalah terjadi dengan MySql
penyedia juga dan tidak dapat direproduksi dengan SqlClient
/SQL Server.
Saya telah menguji contoh yang dicetak tebal (dengan EF 4.3.1) dan tidak dapat mereproduksi masalah:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace EFInclude
{
public class Harbor
{
public int HarborId { get; set; }
public virtual ICollection<Ship> Ships { get; set; }
public string Description { get; set; }
}
public class Ship
{
public int ShipId { get; set; }
public int HarborId { get; set; }
public virtual Harbor Harbor { get; set; }
public virtual ICollection<CrewMember> CrewMembers { get; set; }
public string Description { get; set; }
}
public class CrewMember
{
public int CrewMemberId { get; set; }
public int ShipId { get; set; }
public virtual Ship Ship { get; set; }
public int RankId { get; set; }
public virtual Rank Rank { get; set; }
public int ClearanceId { get; set; }
public virtual Clearance Clearance { get; set; }
public string Description { get; set; }
}
public class Rank
{
public int RankId { get; set; }
public virtual ICollection<CrewMember> CrewMembers { get; set; }
public string Description { get; set; }
}
public class Clearance
{
public int ClearanceId { get; set; }
public virtual ICollection<CrewMember> CrewMembers { get; set; }
public string Description { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Harbor> Harbors { get; set; }
public DbSet<Ship> Ships { get; set; }
public DbSet<CrewMember> CrewMembers { get; set; }
public DbSet<Rank> Ranks { get; set; }
public DbSet<Clearance> Clearances { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
using (var context = new MyContext())
{
context.Database.Initialize(true);
var harbor = new Harbor
{
Ships = new HashSet<Ship>
{
new Ship
{
CrewMembers = new HashSet<CrewMember>
{
new CrewMember
{
Rank = new Rank { Description = "Rank A" },
Clearance = new Clearance { Description = "Clearance A" },
Description = "CrewMember A"
},
new CrewMember
{
Rank = new Rank { Description = "Rank B" },
Clearance = new Clearance { Description = "Clearance B" },
Description = "CrewMember B"
}
},
Description = "Ship AB"
},
new Ship
{
CrewMembers = new HashSet<CrewMember>
{
new CrewMember
{
Rank = new Rank { Description = "Rank C" },
Clearance = new Clearance { Description = "Clearance C" },
Description = "CrewMember C"
},
new CrewMember
{
Rank = new Rank { Description = "Rank D" },
Clearance = new Clearance { Description = "Clearance D" },
Description = "CrewMember D"
}
},
Description = "Ship CD"
}
},
Description = "Harbor ABCD"
};
context.Harbors.Add(harbor);
context.SaveChanges();
}
using (var context = new MyContext())
{
DbSet<Harbor> dbSet = context.Set<Harbor>();
IQueryable<Harbor> query = dbSet;
query = query.Include(entity => entity.Ships);
query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers));
query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Rank)));
query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Clearance)));
var sqlString = query.ToString();
// see below for the generated SQL query
var harbor = query.Single();
Console.WriteLine("Harbor {0} Description = \"{1}\"",
harbor.HarborId, harbor.Description);
foreach (var ship in harbor.Ships)
{
Console.WriteLine("- Ship {0} Description = \"{1}\"",
ship.ShipId, ship.Description);
foreach (var crewMember in ship.CrewMembers)
{
Console.WriteLine("-- CrewMember {0} Description = \"{1}\"",
crewMember.CrewMemberId, crewMember.Description);
Console.WriteLine("-- CrewMember {0} Rank Description = \"{1}\"",
crewMember.CrewMemberId, crewMember.Rank.Description);
Console.WriteLine("-- CrewMember {0} Clearance Description = \"{1}\"",
crewMember.CrewMemberId, crewMember.Clearance.Description);
}
}
Console.ReadLine();
}
}
}
}
Outputnya adalah:
Menurut deskripsi Anda yang dicetak tebal, saya seharusnya memiliki:Anggota Kru 1 Deskripsi ="Peringkat A" dan kekacauan yang sama untuk 3 anggota kru lainnya. Tapi saya tidak punya ini.
Apakah ada sesuatu yang berbeda dalam program pengujian saya dibandingkan dengan kode Anda di mana Anda memiliki kesalahan?
Sunting
SQL yang dihasilkan untuk kueri (lihat baris var sqlString = query.ToString();
pada source code di atas, berikut adalah isi dari sqlString
) adalah:
SELECT
[Project1].[HarborId] AS [HarborId],
[Project1].[Description] AS [Description],
[Project1].[C2] AS [C1],
[Project1].[ShipId] AS [ShipId],
[Project1].[HarborId1] AS [HarborId1],
[Project1].[Description1] AS [Description1],
[Project1].[C1] AS [C2],
[Project1].[CrewMemberId] AS [CrewMemberId],
[Project1].[ShipId1] AS [ShipId1],
[Project1].[RankId] AS [RankId],
[Project1].[ClearanceId] AS [ClearanceId],
[Project1].[Description2] AS [Description2],
[Project1].[RankId1] AS [RankId1],
[Project1].[Description3] AS [Description3],
[Project1].[ClearanceId1] AS [ClearanceId1],
[Project1].[Description4] AS [Description4]
FROM ( SELECT
[Extent1].[HarborId] AS [HarborId],
[Extent1].[Description] AS [Description],
[Join3].[ShipId1] AS [ShipId],
[Join3].[HarborId] AS [HarborId1],
[Join3].[Description1] AS [Description1],
[Join3].[CrewMemberId] AS [CrewMemberId],
[Join3].[ShipId2] AS [ShipId1],
[Join3].[RankId1] AS [RankId],
[Join3].[ClearanceId1] AS [ClearanceId],
[Join3].[Description2] AS [Description2],
[Join3].[RankId2] AS [RankId1],
[Join3].[Description3] AS [Description3],
[Join3].[ClearanceId2] AS [ClearanceId1],
[Join3].[Description4] AS [Description4],
CASE WHEN ([Join3].[ShipId1] IS NULL) THEN CAST(NULL AS int) WHEN ([Join3].[CrewMemberId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
CASE WHEN ([Join3].[ShipId1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM [dbo].[Harbors] AS [Extent1]
LEFT OUTER JOIN (SELECT [Extent2].[ShipId] AS [ShipId1], [Extent2].[HarborId] AS [HarborId], [Extent2].[Description] AS [Description1], [Join2].[CrewMemberId], [Join2].[ShipId2], [Join2].[RankId1], [Join2].[ClearanceId1], [Join2].[Description2], [Join2].[RankId2], [Join2].[Description3], [Join2].[ClearanceId2], [Join2].[Description4]
FROM [dbo].[Ships] AS [Extent2]
LEFT OUTER JOIN (SELECT [Extent3].[CrewMemberId] AS [CrewMemberId], [Extent3].[ShipId] AS [ShipId2], [Extent3].[RankId] AS [RankId1], [Extent3].[ClearanceId] AS [ClearanceId1], [Extent3].[Description] AS [Description2], [Extent4].[RankId] AS [RankId2], [Extent4].[Description] AS [Description3], [Extent5].[ClearanceId] AS [ClearanceId2], [Extent5].[Description] AS [Description4]
FROM [dbo].[CrewMembers] AS [Extent3]
INNER JOIN [dbo].[Ranks] AS [Extent4] ON [Extent3].[RankId] = [Extent4].[RankId]
LEFT OUTER JOIN [dbo].[Clearances] AS [Extent5] ON [Extent3].[ClearanceId] = [Extent5].[ClearanceId] ) AS [Join2] ON [Extent2].[ShipId] = [Join2].[ShipId2] ) AS [Join3] ON [Extent1].[HarborId] = [Join3].[HarborId]
) AS [Project1]
ORDER BY [Project1].[HarborId] ASC, [Project1].[C2] ASC, [Project1].[ShipId] ASC, [Project1].[C1] ASC