Bewerken
De onderstaande test is gemaakt met SQL Server en SqlClient
als aanbieder. Het feit dat het probleem niet reproduceerbaar is met SQL Server roept de vraag op of de MySql
provider die u gebruikt, heeft een bug die een onjuiste SQL maakt voor uw LINQ-query. Het lijkt op hetzelfde probleem als in deze vraag
waar het probleem zich voordeed met een MySql
provider ook en kon niet worden gereproduceerd met SqlClient
/SQL-server.
Ik heb het vetgedrukte voorbeeld getest (met EF 4.3.1) en kan het probleem niet reproduceren:
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();
}
}
}
}
De uitvoer is:
Volgens je vetgedrukte beschrijving zou ik moeten hebben:Bemanningslid 1 Beschrijving ="Rank A" en dezelfde rotzooi voor de andere 3 bemanningsleden. Maar ik heb dit niet.
Is er iets anders in mijn testprogramma in vergelijking met jouw code waar je de fout hebt?
Bewerken
De gegenereerde SQL voor de query (zie regel var sqlString = query.ToString();
in de broncode hierboven is het volgende de inhoud van sqlString
) is:
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