2010-09-05 12 views
5

estoy tratando de resolver un problema similar al que se describe aquícódigo de proyección repetida en Entity Framework

Initializing strongly typed objects in LINQ to Entities

sólo de totalmente la dirección opuesta. Tengo varias funciones en mi repositorio, todas las cuales devuelven datos con formas idénticas. El problema es mi código de proyección:

select new pocoClass 
{ 
    // complex projection that is several pages long includes grabbing a graph of data 
} 

en el momento en que existe para cada consulta en el repositorio. Intenté moverlo a un inicializador de objetos, pero eso me da el temido "Solo los constructores y los inicializadores sin parámetros son compatibles con LINQ to Entities". problema.

Yo probé la división en dos consultas

var candidates = (from thing in _entities.whatever 
    where (complex.stuff==true) 
    select thing); 

var final = (from thing in candidates.AsEnumerable() 
    let x = thing.ITEMS.Where(blah=>blah.blah==param) 
    let y = x.OTHERITEMS.FirstOrDefault() 
    select new pocoClass(thing,x,y); 

pero aquí final es siempre nula y el código de nuevo pocoClass nunca es llamado. He incluido el let x & y en el anterior porque estos siempre varían entre cada uso de la proyección.

Entonces, ¿tengo que volver a varias copias de mi proyección o hay otra manera de salir de esto?

Respuesta

12

No estoy seguro si esto es útil para usted, pero lo que a menudo hago es crear métodos de proyección que toman un IQueryable y devuelven un IQueryable para traducir de un objeto de dominio a un DTO. Se parecen mucho a esto:

public static IQueryable<CustomerDTO> ToCustomerDTO(
    IQueryable<Customer> customers) 
{ 
    return 
     from customer in customers 
     select new CustomerDTO() 
     { 
      ... 
     }; 
} 

Esto me permite tener esta proyección en un solo lugar. Desde varios lugares en mi capa de negocios llamo a tal método.

Hay algunas cosas a tener en cuenta, sin embargo:

  • asegurarse de que estos métodos de proyección no contienen ninguna lógica de negocio. Tener filtros de casos de uso específicos sería malo.
  • A veces tiene un DTO que contiene un gráfico de objeto complejo que desea extraer de manera eficiente de la base de datos en una sola consulta. Con un poco de creatividad, esto a menudo es posible, pero no al devolver un IQueryable. En ese caso, devuelvo una matriz de DTO.
  • Coloco esos métodos de proyección como métodos estáticos dentro de la clase DTO. Si bien este no es un diseño muy limpio, descubrió que hace que el código sea muy fácil de mantener.

Espero que esto ayude.

+0

Casi - es el problema de la lógica de negocios - en mi ejemplo, las declaraciones de let que se evalúan para cada cliente antes de la proyección. – Andiih

+0

En realidad, eso es suficiente para darme una solución. Creé una nueva clase intermedia DTO simplificada que puedo proyectar en su lugar simplemente copiando una media docena de valores: cada uno es una entidad EF completa. Luego utilizo su solución para hacer la proyección final de esas entidades. No estoy seguro de cómo va a funcionar, pero es ciertamente más limpio! – Andiih

+0

@Andiih: Deberá usar el generador de perfiles SQL para ver cuántas consultas se ejecutan en segundo plano. Hay un buen cambio que EF ejecutará muchas consultas detrás de las coberturas. La tecnología, por supuesto, tiene sus límites. Si no está satisfecho con el rendimiento y no tiene idea de cómo obtenerlo en una sola consulta, quizás pueda ayudarlo con eso. En ese caso, comience una nueva pregunta aquí en SO y coloque un enlace aquí.Aclamaciones – Steven

Cuestiones relacionadas