2012-10-01 96 views
5

Utilizando Entity Framework LINQ, me gustaría devolver una clase padre para cada tabla padre y llenar una propiedad, cuyo tipo es una interfaz, en la clase padre con una de múltiples implementaciones concretas de una interfaz. Qué implementación concreta se debe determinar en el momento de la consulta según el valor de un campo en la tabla padre.EF4 No se puede convertir tipo concreto a la interfaz

En un ejemplo muy simplificado, tengo 3 tablas y 3 POCOs correspondientes.

tablas simples para el bien de ejemplo

Three Tables: Master and two children

clases simples para el bien de ejemplo

internal interface IConfiguration 
{ 
} 

internal class ConfigurationContainer 
{ 
    public IConfiguration Config { get; set; } 
} 

internal class ConfigurationSouth : IConfiguration 
{ 
} 

internal class ConfigurationNorth : IConfiguration 
{ 
} 

Desafortunadamente, recorrer todos los resultados de los padres y determinar qué subconsulta para usar mientras está dentro del ciclo. Algo como este bloque.

foreach (var configMaster in db.ConfigMasters.ToList()) 
{ 
    var configContainer = new ConfigurationContainer(); 
    if (configMaster.IsNorth) 
     configContainer.Config = (from x in db.ConfigNorths 
          select new ConfigurationNorth()) 
             .FirstOrDefault(); 
    else 
     configContainer.Config = (from x in db.ConfigSouths 
          select new ConfigurationSouth()) 
             .FirstOrDefault(); 
} 

Looping a través de cada uno de los registros principales para realizar una subconsulta es menos que óptimo. Realmente me gustaría que EF LINQ realice la consulta en un solo viaje a la base de datos, así como las proyecciones en mis POCO.

Se me ocurrió este LINQ para consultar la base de datos en un solo viaje y devolver los objetos proyectados de modo que la propiedad Config se llene por una de las dos subconsultas en querytime. Aunque se compila, arroja una excepción en tiempo de ejecución.

using (var db = new Entities()) 
{ 
    var qry = from cfgMaster in db.ConfigMasters 
       let configNorth = (from x in db.ConfigNorths 
            select new ConfigurationNorth()) 
        .FirstOrDefault() 
       let configSouth = (from x in db.ConfigSouths 
            select new ConfigurationSouth()) 
        .FirstOrDefault() 
       select new ConfigurationContainer() 
        { 
         Config = cfgMaster.IsNorth ? configNorth : (IConfiguration) configSouth 
        }; 

    var results = qry.ToList(); 
} 

Excepción

Excepción no controlada: System.NotSupportedException: No se puede convertir el tipo 'EFTest.ConfigurationNorth' al tipo 'EFTest.IConfiguration'. LINQ a Entidades solo admite la fundición de tipos primitivos de Entity Data Model.

+0

Solo se puede hacer de esta manera cuando permite que ambas clases se deriven de una clase base que también forma parte del modelo. –

+0

:(Desafortunadamente, parece que estás en lo correcto. Si publicas eso como respuesta, lo aceptaré. –

Respuesta

1

Entity Framework no (¿todavía?) Admite el uso de interfaces de esta manera, básicamente porque la interfaz no está (y no puede) registrada con el modelo. Lo que quiere solo es posible cuando permite que ambas clases se derivan de una clase base que también forma parte del modelo.

Cuestiones relacionadas