2009-09-17 12 views
11

Tengo un objeto CLR simple y antiguo que es esencialmente un contenedor para dos objetos de marco de entidad, estoy haciendo esto para poder pasar este objeto contenedor a una vista fuertemente tipada en el marco MVC . Mi clase foo envoltorio es muy simple:Inicializando objetos fuertemente tipados en LINQ a Entidades

public class FooWrapper 
{ 
    public FooWrapper(Foo f, Bar b) 
    { 
     this.FooObject = f; 
     this.BarObject = b; 
    } 

    public Foo FooObject { get; private set; } 
    public Bar BarObject { get; private set; } 
} 

Lo que tengo hasta ahora para mi función ListFoosWithBars es el siguiente:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

Esto no funciona porque evidentemente LINQ a Entidades no soporta parametrizada inicialización, se lanza una excepción que dice simplemente eso: "Sólo los constructores y los inicializadores sin parámetros son compatibles con LINQ para Entidades". Me preguntaba si hay otra forma de lograr el mismo resultado.

Respuesta

20

si añade un constructor sin parámetros a su FooWrapper y luego usar inicialización de objetos en su lugar, de este modo:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper() 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+3

Tenía lo mismo escrito, usted gana. – AdamSane

+0

Perfecto, gracias! –

3

Pruebe una inicialización diferente:

public class FooWrapper 
{ 
    public FooWrapper() { } 

    public Foo FooObject { get; set; } 
    public Bar BarObject { get; set; } 
} 


public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+1

+1 para omitir() después del nombre del tipo en el inicializador. :) –

12

Ok, pero lo que si quieres FooObject y BarObject para ser de solo lectura? Me parece un poco retrógrado que nieguen la posibilidad de usar un constructor en el objeto.

Veo mucha gente rompiendo buenas prácticas de encapsulado para utilizar la inicialización de objetos en este escenario.

6

Por qué no está usando el .AsEnumerable()? De esa forma, no necesitará crear un constructor sin parámetros y eso es lo que desea.

Su código era casi bueno. Cambiarlo a esto:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet.AsEnumerable() 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

que tenían el mismo problema hoy en día. Tuve una clase con un constructor de parámetros. Este constructor llenó un campo de solo lectura privado que fue devuelto por una propiedad solo con un get y no con un conjunto.

+0

¡Esta es la mejor solución para este problema! –

+8

Sin embargo, sería muy cuidadoso con este enfoque, básicamente estás negando los beneficios del marco Entity llamando a AsEnumerable. Una vez que especifique que está reuniendo efectivamente todos los registros de la Tabla FooSet y luego realizando la unión localmente en la memoria. Solo piense en las implicaciones de rendimiento cuando tiene miles (o millones) de registros. – Alan

+0

@Santo De acuerdo, este enfoque hace que mi máquina se detenga con una instrucción LINQ en 16 tablas, tarda unos cinco minutos en devolver un resultado. Lo hizo casi instantáneamente con una declaración SQL comparable. – wonea

Cuestiones relacionadas