2012-04-13 22 views
12

He buscado un tema similar a mi pregunta en Internet durante los últimos días. Finalmente recurrí a hacer esta pregunta yo mismo.Correlación de resultados del procedimiento almacenado de Entity Framework

Utilizando la metodología de primer código y EF 4.3.1 Creé una clase de contexto, clases de entidad y clases para almacenar la salida del procedimiento almacenado. La clase de contexto tiene métodos que ejecutan ciertos procedimientos almacenados usando SqlQuery<T>.

Ejemplo:

public IEnumerable<Results> GetData(int id) 
{ 
    var parameters = new SqlParameter[] { new SqlParameter("@id", id) }; 
    var result = this.Database.SqlQuery<Result>("Exec dbo.sproc_GetData @id", parameters); 
    var data= result.ToList<Result>(); 

    return data; 
} 

Como estoy Trazado de mi depuración mis datos regresa, y los datos se asigna a propiedades con un nombre coincidente. Sin embargo, en el resultado hay una columna con un "/" en el nombre (ejemplo: Info/Data). Obviamente, no puedo nombrar una propiedad de esa manera, así que pensé que podía mapear la salida utilizando el atributo de columna ([Column("Info/Data")]):

[Column("Info/Data")] 
public string InfoData 
{ 
    get { return infoData; } 
    set { infoData= value; } 
} 

Incluso he intentado utilizar el operador pie de la letra ([Column(@"Info/Data")]), envolviendo el texto con [] ([Column("[Info/Data]")]), y probé ambos ([Column(@"[Info/Data]")]). Al recorrer el código, veo que se asignan propiedades con nombres de columna coincidentes, pero las propiedades con el atributo de columna se ignoran y se pasan por alto durante la asignación.

También probé con fluidez-api para cada columna de la entidad.

modelBuilder.ComplexType<Result>().Property(d => d.InfoData).HasColumnName("Info/Data"); 

pero que desencadena la siguiente excepción:

El lector de datos es incompatible con la especificada 'NameSpace.Result'. Un miembro del tipo, 'InfoData', no tiene una columna correspondiente en el lector de datos con el mismo nombre.

En mi proyecto NameSpace.Result es una clase (nombre cambiado por seguridad) y InfoDatais es la propiedad que intento trazar usando fluidez-API (la columna de SQL correspondiente tiene un/en ella; por ejemplo: información/datos) .

¿Alguien ha encontrado este problema?

Si mi problema no está claro o se ha preguntado antes, por favor hágamelo saber.

+7

Me pregunto qué tipo de personas nombre Clases/Tablas de base de datos con "/" personaje. –

+0

Eso hace que dos de nosotros. No escribí el proceso. Me dijeron que use los datos. Fue muy molesto ver el aliasing sucediendo. –

+0

¿Hay alguna posibilidad de crear envoltorio SP con nombres de columna normales en el resultado? – vittore

Respuesta

3

Me doy cuenta de que esta es una vieja pregunta ahora, pero como ha sido impulsada por la respuesta reciente OPs, tal vez todavía hay interés en ello.

Si está atascado con ese proceso almacenado tal como está y devuelve nombres de columna incompatibles con EF, dado que está pasando SQL para llamar directamente al proc con SqlQuery, podría usar el método INSERT-EXEC para hacer algo como declarar una variable de tabla (con más nombres de columna compatibles), INSERT-EXEC el proc almacenado en la variable de tabla, luego seleccionar de la variable de tabla como su conjunto de resultados?

Sería SQL de largo aliento para pasar y así que no sea una solución agradable, pero como un ejercicio de reflexión para ver si eso es una forma de evitar el problema, pensé que lo ofrecería.

Aquí hay un buen artículo sobre este tipo de problema: http://www.sommarskog.se/share_data.html - la mayoría de los métodos no son útiles ya que no se puede cambiar el proceso almacenado (y probablemente tener poco o ningún acceso a la estructura db o hacer cambios en él en absoluto?), pero el método INSERT-EXEC aparece como una posible solución sin la necesidad de cambiar nada en el nivel db ...

+0

Me había olvidado por completo de Insert-Exec, ya que solo he leído sobre él y nunca lo he usado. Es una solución mucho mejor que usar OPENROWSET como lo hice en mi respuesta. Esta es ciertamente una solución posible, ya que le permitirá enmascarar nombres de columnas mal formados. –

0

Puede que no sea posible hacer lo que quiera. Al usar Raw SQL, la porción de asignación de EF se pasa por alto.

How to use Entity Framework to map results of a stored procedure to entity with differently named parameters

Lo mismo con ExecuteStoreQuery http://social.msdn.microsoft.com/Forums/pl/adonetefx/thread/d524b005-12a4-4300-a974-1e0582de876b

Se podría utilizar el ObjectQuery para obtener una lista de objetos DBDataRecord. Luego use la función Linq "Seleccionar" para mapear los resultados a su tipo de objeto. Si ajusta esa asignación en una función de extensión que toma un IEnumerable y devuelve un IEnumberable.

Return Custom Object <List T> from Entity framework and assign to Object Data Source

+0

Terminé abandonando el proyecto de código primero y fui con el diseñador en esta instancia. Se mantendrá de esta manera hasta que el soporte de mapas llegue a las llamadas a procedimientos almacenados. Gracias –

0

Volviendo y pensando en este problema uno de los más simples (no soluciones potencialmente más limpios o mejores) es envolver todo el conjunto de resultados en un nuevo procedimiento. Por supuesto, si tiene la capacidad de modificar el procedimiento sin romper nada, esa es su mejor solución.Sin embargo, si no puede modificar la salida, una solución es usar OPENROWSET (mire la respuesta de Aaron) para tomar el resultado del procedimiento en una tabla y seleccionar cada columna con un nuevo alias que funcione y se adhiera a principios de programación más limpios.

Espero que esto ayude a cualquiera en el futuro.

NOTA:
yo no he comprobado si la nueva versión de EF ha resuelto este problema.

Cuestiones relacionadas