Использование лямбда-выражения для выбора различных полей из имен полей - PullRequest
7 голосов
/ 18 ноября 2010

Мне нужно получить два поля из таблицы базы данных (извлеченных с использованием linq-to-sql), одно поле является датой-временем (и является фиксированным полем), а другое всегда является десятичным, но поле может отличаться.

В таблице содержатся данные о валютах, которые обрабатываются два раза в день и в разных валютах, поэтому могут иметь такие поля, как AM_USD, PM_USD, AM_EUR и т. Д. И мне нужно получить данные, такие как список дат для PM_USD илидата против AM_EUR.

Я хотел бы иметь возможность вызывать данные, используя, например, лямбда-выражение (это выделенный пример):

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

Я пыталсянапишите функцию, чтобы сделать это, и я потерпел неудачу.

Самое близкое, что мне удалось сделать, это:

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();
}

, который завершается с ошибкой «System.InvalidOperationException: лямбда-параметр не в области».

Я уверен, что упустил что-то очевидное или ошибся.

Есть идеи?

Спасибо T

Ответы [ 2 ]

4 голосов
/ 18 ноября 2010

x.Foo является членом из x (свойство или поле), а не параметром:

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();
}
3 голосов
/ 18 ноября 2010

Из вашего вопроса:

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

Задать имя поля в запросе LINQ в виде строки можно с помощью библиотеки динамических запросов LINQ .

Вы можете использовать библиотеку DynamicQuery против любого поставщика данных LINQ (включая LINQ to SQL, LINQ to Объекты, LINQ to XML, LINQ to Сущности, LINQ to SharePoint, LINQ to TerraServer и т. Д.). Вместо того, чтобы использовать операторы языка или лямбда с безопасным типом методы расширения, чтобы построить свой LINQ запросы, динамический запрос библиотека предоставляет вам строки на основе методы расширения, которые вы можете передать любое строковое выражение в.

И, кстати, даже мысль, что вопрос не совсем идентичен, ответ почти такой же.

...