2010-11-18 11 views
7

Necesito obtener dos campos de una tabla de base de datos (recuperada usando linq-to-sql), un campo es una fecha y un campo fijo y el otro siempre un decimal, pero el campo puede ser diferente.Usando Lambda Expression para seleccionar campos diferentes de los nombres de campo

La tabla contiene datos de divisas que se procesan dos veces al día y en diferentes monedas, por lo que podría tener campos como AM_USD, PM_USD, AM_EUR, etc. Y necesito obtener datos como una fecha de PM_USD o la fecha contra AM_EUR.

Me gustaría ser capaz de llamar a los datos usando una expresión lambda, por ejemplo (esto es un despojado ejemplo):

data = TableData.Select(x=>new {x.DateTimeAdded, x.[**field name as string**]}); 

he estado tratando de escribir una función para hacer esto, y estoy fallando tristemente

El más cercano que he conseguido es:

private Func<TableData, KeyValuePair<DateTime, decimal>> CreateSelect(string FieldName) 
{ 
    var parameterExp = Expression.Parameter(typeof(TableData), "sel"); 
    var dateParameter = Expression.Parameter(typeof(DateTime), "DateTimeAdded"); 
    var fieldParameter = Expression.Parameter(typeof(decimal), FieldName); 
    ConstructorInfo constructorInfo = typeof(KeyValuePair<DateTime, decimal>).GetConstructor(new[] { typeof(DateTime), typeof(decimal) }); 
    NewExpression constructExpression = Expression.New(constructorInfo, new ParameterExpression[] { dateParameter, fieldParameter}); 

    var lambda = Expression.Lambda<Func<TableData, KeyValuePair<DateTime, decimal>>>(constructExpression, parameterExp); 

    return lambda.Compile(); 
} 

Qué falla con "System.InvalidOperationException: Lambda parámetro no alcance".

Estoy seguro de que me falta algo obvio, o lo estoy haciendo mal.

¿Alguna idea?

Gracias T

+0

¿Es justo suponer que no puede alterar ese terrible esquema para los datos? – Lazarus

Respuesta

4

x.Foo es un miembro de x (propiedad o campo), no es un parámetro:

private Func<TableData, KeyValuePair<DateTime, decimal>> CreateSelect(string FieldName) 
{ 
    var parameterExp = Expression.Parameter(typeof(TableData), "sel"); 
    var dateProp = Expression.PropertyOrField(parameterExp, "DateTimeAdded"); 
    var fieldProp = Expression.PropertyOrField(parameterExp, FieldName); 
    ConstructorInfo constructorInfo = typeof(KeyValuePair<DateTime, decimal>).GetConstructor(new[] { typeof(DateTime), typeof(decimal) }); 
    NewExpression constructExpression = Expression.New(constructorInfo, new [] { dateProp, fieldProp}); 

    var lambda = Expression.Lambda<Func<TableData, KeyValuePair<DateTime, decimal>>>(constructExpression, parameterExp); 

    return lambda.Compile(); 
} 
+0

Hola Marc, esta es una gran respuesta y está devolviendo la epxresión correcta, pero ahora voy a sonar tonto ... ¿Cómo llamo a este método? var data = TableData.Select (CreateSelect ("nombre de campo")); regresa con una System.ArgumentNullExpception y me pide que "intente especificar el tipo explicity argumentos" Gracias T –

+0

@Toby - ¿Dónde error? –

+0

@Marc - No me deja compilar el código. Esta línea funciona bien: var tst = CreateSelect ("AMUSD"); Pero si intento algo como data.Select (CreateSelect ("AMUSD")); no me deja compilar. –

3

Desde su pregunta:

data = TableData.Select(x=>new {x.DateTimeAdded, x.[**field name as string**]}); 

Especificación del campo nombre en una consulta LINQ como una cadena se puede hacer usando the LINQ Dynamic Query Library.

You can use the DynamicQuery library against any LINQ data provider (including LINQ to SQL, LINQ to Objects, LINQ to XML, LINQ to Entities, LINQ to SharePoint, LINQ to TerraServer, etc). Instead of using language operators or type-safe lambda extension methods to construct your LINQ queries, the dynamic query library provides you with string based extension methods that you can pass any string expression into.

Y, por cierto, pese a que la question no es exactamente idéntica, la answer es más o menos lo mismo.

+0

* una * respuesta; no hay * la * respuesta aquí. –

+0

@Marc Gravell: no estoy seguro de si me perdí una broma gramatical o algo así (el inglés no es mi lengua materna), pero me vinculé a * a * respuesta específica, y no veo nada de malo al referirme a eso como _la_ respuesta (como en _la_ respuesta a la que me he vinculado) ... – Nailuj

+0

Lo leí como "la respuesta a esta categoría de pregunta", donde "el" (siendo el artículo singular y definido) se refiere a "el único posible, sensato, sensible" responde a esta categoría de pregunta ". No es importante, pero lingüísticamente, quizás "esto" hubiera sido más claro que "el". –

Cuestiones relacionadas