2010-06-07 17 views
5

¿Alguien me puede mostrar cómo indicar qué columnas me gustaría que volviera en tiempo de ejecución desde una instrucción LINQ To SQL?LINQ To SQL Dynamic Select

Estoy permitiendo que el usuario seleccione elementos en una lista de casilla de verificación que representa las columnas que les gustaría mostrar en una vista de cuadrícula que está vinculada a los resultados de una consulta L2S.

Puedo generar dinámicamente la cláusula WHERE pero no puedo hacer lo mismo con la pieza SELECCIONAR. Este es un ejemplo:

var query = from log in context.Logs select log; 
       query = query.Where(Log => Log.Timestamp > CustomReport.ReportDateStart); 
       query = query.Where(Log => Log.Timestamp < CustomReport.ReportDateEnd); 
       query = query.Where(Log => Log.ProcessName == CustomReport.ProcessName); 

       foreach (Pair filter in CustomReport.ExtColsToFilter) 
       { 
        sExtFilters = "<key>" + filter.First + "</key><value>" + filter.Second + "</value>"; 
        query = query.Where(Log => Log.FormattedMessage.Contains(sExtFilters)); 
       } 
+1

re el alcance de la variable 'sExtFilters': http://stackoverflow.com/questions/1095707/what-is-the-exact-definition-of-a-closure/1095770#1095770 –

+1

¡El temido cierre de bucle! –

+0

P.S. Estoy eliminando la etiqueta 'dynamic-linq' porque esa etiqueta se refiere a la [extensión de consulta dinámica] (http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1 -using-the-linq-dynamic-query-library.aspx) (nota: eso no te ayudará aquí, por desgracia). – Aaronaught

Respuesta

3

La respuesta corta es No.

Un método debe tener un tipo de devolución conocido y específico. Ese tipo puede ser System.Object pero luego tienes que usar un gran código de reflejo feo para obtener realmente a los miembros. Y en este caso también tendría que usar un feo reflexión código del árbol de expresiones para generar el valor de retorno.

Si intenta generar dinámicamente las columnas en el lado de la interfaz de usuario, deje de hacer eso. Defina las columnas en el momento del diseño, luego simplemente muestre/oculte las columnas que realmente necesita/desea que el usuario vea. Haga que su consulta devuelva todas las columnas que pueden ser visibles.

A menos que note un serio problema de rendimiento al seleccionar todas las columnas de datos (en cuyo caso, probablemente tenga problemas de índices que no cubran a nivel de base de datos), entonces estará mucho mejor con este enfoque. Está perfectamente bien generar predicados y ordenar órdenes dinámicamente pero realmente no quieres hacer esto con la lista de salida.


Algunos de los comentarios que me han obligado a considerar seriamente si estaba o no correcta en mi implicación de que una lista de salida dinámica es en realidad posible, y llego a la conclusión de que es, a pesar de ser una peligrosa nadar contra la idea actual. Para realizar este truco, debe:

  1. Generar un nuevo tipo usando Reflection.Emit.
  2. Genera un árbol de expresiones que lo inicializa usando Expression.MemberInit.
  3. Compila la expresión y pásala al método Select.
  4. Devuelva un System.Object de tipo débil según su método y use Reflection para acceder a los miembros por su nombre.

No es el tipo de cosas que siempre querría ver en el código de producción, pero ahí lo tienen, es posible.

+0

Bueno, no era la respuesta que estaba buscando, sacas un punto interesante. – mcass20

+0

¿Es esto incluso * posible * con L2S? Los tipos anónimos utilizados en L2S para selecciones personalizadas son todos generados en tiempo de compilación; Me sorprendería si esto fuera incluso algo que es posible hacer incluso como un ejercicio intelectual. –

+0

@ Adam: Es teóricamente posible si construyes dinámicamente un árbol de expresiones para el 'Seleccionar'. Digo teóricamente porque no lo he intentado, ni tampoco lo haría.;) – Aaronaught

1

No necesita hacer eso en el nivel de consulta (eso sería bastante difícil de todos modos, ya que necesitaría crear dinámicamente un tipo en tiempo de ejecución) ... Es mucho más fácil manejar eso en el GridView, al declarar explícitamente las columnas que desea mostrar.