¿Cómo puedo usar Entity Framework en un gráfico de objetos más allá de 2 con MySQL Connector / NET?

Aquí hay un informe de error confirmado con Oracle:http://bugs.mysql.com/bug.php?id=67183

Situación

Cuando se utiliza un.Include dentro de mi repositorio, noté que estaba obteniendo resultados extraños, principalmente porque los valores consultados que se devolvían eran de los campos incorrectos (el nombre terminaría en la descripción, por ejemplo), pero en la base de datos todos los valores son correctos, solo aparece mal después de la consulta). Cambié los nombres para que las relaciones sean más obvias, pero la estructura es la misma. Sigo obteniendo los valores incorrectos para el miembro de la tripulación asociado y su rango y separación relativos. Parece que si hay un nombre de campo que es el mismo en CrewMember que Rank, entonces el valor de ese campo en Rank se convierte en lo que era el valor en CrewMember. Por ejemplo, si Rank tenía una descripción, y también CrewMember, la descripción de Rank para el CrewMember sería la descripción del CrewMember.

Entity Framework no puede realizar consultas bien formadas más allá de 2 cuando hay campos similares definidos como resultado de que el proveedor MySQL Connector / NET sql no se forme correctamentejoin declaraciones

Definiciones

Esta es una definición de clase que modela una tabla de base de datos. Estoy utilizando C # ASP.NET MVC 3 con Entity Framework 4.1 y MySQL Connector / NET versión 6.5

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

Consulta

Este es el código que consulta la base de datos y tiene la consulta y las llamadas .Include.

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

Son estos.Include llamadas bien formadas? ¿Me he perdido algo?

Esto es bastante complejo, así que si tiene alguna pregunta, hágamelo saber en los comentarios e intentaré aclarar cualquier cosa que pueda haber omitido.

¿Cómo puedo usar Entity Framework para obtener una consulta bien formada en un gráfico de objetos más allá de 2 cuando utilizo MySQL Connector / NET?

Ediciones

Aquí está la consulta generada:

{SELECT
[Project1].[HarborId], 
[Project1].[Description], 
[Project1].[C2] AS [C1], 
[Project1].[ShipId], 
[Project1].[HarborId1], 
[Project1].[Description1], 
[Project1].[C1] AS [C2], 
[Project1].[CrewMemberId], 
[Project1].[ShipId1], 
[Project1].[ClearanceId], 
[Project1].[RankId], 
[Project1].[Description2], 
[Project1].[RankId1], 
[Project1].[Description3], 
[Project1].[ClearanceId1], 
[Project1].[Description4], 
FROM (SELECT
[Extent1].[HarborId], 
[Extent1].[Description], 
[Join3].[ShipId], 
[Join3].[HarborId] AS [HarborId1], 
[Join3].[Description]AS [Description1], 
[Join3].[CrewMemberId], 
[Join3].[ShipId]AS [ShipId1], 
[Join3].[ClearanceId], 
[Join3].[RankId], 
[Join3].[Description] AS [Description2], 
[Join3].[RankId] AS [RankId1], 
[Join3].[Description] AS [Description3], 
[Join3].[ClearanceId] AS [ClearanceId1], 
[Join3].[Description] AS [Description4], 
CASE WHEN ([Join3].[ShipId] IS  NULL) THEN (NULL)  WHEN ([Join3].[CrewMemberId] IS  NULL) THEN (NULL)  ELSE (1) END AS [C1], 
CASE WHEN ([Join3].[ShipId] IS  NULL) THEN (NULL)  ELSE (1) END AS [C2]
FROM [Harbor] AS [Extent1] LEFT OUTER JOIN (SELECT
[Extent2].[ShipId], 
[Extent2].[HarborId], 
[Extent2].[Description], 
[Join2].[CrewMemberId], 
[Join2].[ShipId] AS [ShipID1], 
[Join2].[ClearanceId], 
[Join2].[RankId], 
[Join2].[Description] AS [DESCRIPTION1], 
[Join2].[RankID1], 
[Join2].[DESCRIPTION1] AS [DESCRIPTION11], 
[Join2].[ClearanceID1], 
[Join2].[DESCRIPTION2], 
FROM [Ship] AS [Extent2] LEFT OUTER JOIN (SELECT
[Extent3].[CrewMemberId], 
[Extent3].[ShipId], 
[Extent3].[ClearanceId], 
[Extent3].[RankId], 
[Extent3].[Description], 
[Extent4].[RankId] AS [RankID1], 
[Extent4].[Description] AS [DESCRIPTION1], 
[Extent5].[ClearanceId] AS [ClearanceID1], 
[Extent5].[Description] AS [DESCRIPTION2], 
FROM [CrewMember] AS [Extent3] INNER JOIN [Rank] AS [Extent4] ON [Extent3].[RankId] = [Extent4].[RankId] LEFT OUTER JOIN [Clearance] AS [Extent5] ON [Extent3].[ClearanceId] = [Extent5].[ClearanceId]) AS [Join2] ON [Extent2].[ShipId] = [Join2].[ShipId]) AS [Join3] ON [Extent1].[HarborId] = [Join3].[HarborId]
 WHERE [Extent1].[HarborId] = @p__linq__0) AS [Project1]
 ORDER BY 
[Project1].[HarborId] ASC, 
[Project1].[C2] ASC, 
[Project1].[ShipId] ASC, 
[Project1].[C1] ASC}

Aclaración

El uso de las relaciones de inclusión en 1-1 no plantea ningún problema cuando parece que "profundizar" de esta manera. Sin embargo, el problema parece surgir cuando hay 1-muchas relaciones como parte de la perforación. La perforación es necesaria para la carga impaciente.

La primera proyección,entity => entity.Ships.Select(s => s.CrewMembers, devolverá una lista de miembros de la tripulación que están relacionados con cada barco. Esto devuelve correctamente el gráfico donde un puerto contiene una lista de barcos, cada uno con una lista de miembros de la tripulación.

Sin embargo, la segunda proyección.CrewMembers.Select(cm => cm.Rank, de hecho no devuelve la pieza adecuada de la gráfica. Los campos comienzan a mezclarse, y cualquier campo que comparta el mismo nombre se establecerá de manera predeterminada en el campo principal. Esto da como resultado resultados inconsistentes y, lo que es más importante, malos datos. El hecho de que no se produzcan errores lo empeora, ya que esto solo se puede determinar mediante una inspección en tiempo de ejecución.

Si hubiera una manera de obtener de alguna manera una respuesta única fuertemente tipada (en oposición a una lista) de la primera proyección, tal vez la segunda no sería necesaria. Tal como está ahora, creo que el problema radica en la primera proyección que devuelve una lista. Cuando la segunda proyección intenta proyectar basándose en esa lista en lugar de hacerlo desde un solo objeto, se introduce el error lógico.

Si, en lugar de que los CrewMembers sean una ICollection, era solo un CrewMember, entonces esta proyección anidada devolverá los datos correctos. Sin embargo, esa es una versión simplificada de este problema y, lamentablemente, es lo que casi todas las pruebas parecen haberse realizado en los diversos blogs, tutoriales, publicaciones, artículos y documentos que revisé al tratar de resolver este problema.

Respuestas a la pregunta(3)

Su respuesta a la pregunta