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
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.
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. –
:(Desafortunadamente, parece que estás en lo correcto. Si publicas eso como respuesta, lo aceptaré. –