【问题标题】:Using Lambda Expression to Select different fields from field names使用 Lambda 表达式从字段名称中选择不同的字段
【发布时间】:2010-11-18 12:45:47
【问题描述】:

我需要从数据库表中获取两个字段(使用 linq-to-sql 检索),一个字段是日期时间(并且是固定字段),另一个始终是小数,但字段可以不同。

该表包含每天处理两次并以不同货币处理的货币数据,因此可能包含 AM_USD、PM_USD、AM_EUR 等字段。我需要获取数据,例如针对 PM_USD 的日期列表或针对的日期AM_EUR。

例如,我希望能够使用 lambda 表达式调用数据(这是一个剥离的示例):

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:Lambda 参数不在范围内”。

我确定我遗漏了一些明显的东西,或者以错误的方式处理它。

有什么想法吗?

谢谢 T

【问题讨论】:

  • 假设您不能更改数据的糟糕架构是否公平?

标签: c# asp.net linq-to-sql lambda expression


【解决方案1】:

x.Foox(属性或字段)的成员,而不是参数:

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

【讨论】:

  • 嗨,马克,这是一个很好的答案,并且正在返回正确的表达式,但现在我听起来很愚蠢......我该如何调用这个方法? var data = TableData.Select(CreateSelect("fieldname"));返回一个 System.ArgumentNullExpception 并要求我“尝试明确指定类型参数”谢谢 T
  • @Marc - 它不会让我编译代码。此行工作正常: var tst = CreateSelect("AMUSD");但是,如果我尝试类似 data.Select(CreateSelect("AMUSD"));它不会让我编译。
  • @Marc 完整错误:方法 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' 不能从用法中推断出来。尝试明确指定类型参数
  • @Toby - 你能举一个可重现的例子吗?即 data 是什么?这对我来说很好:
  • IQueryable source = new[] { new TableData { DateTimeAdded = DateTime.Today, Foo = 123.45M}, new TableData { DateTimeAdded = DateTime.Now, Foo = 678.90M}, }。 AsQueryable(); var projection = source.Select(CreateSelect("Foo")); var dictionary = projection.ToDictionary(x => x.Key, x => x.Value);
【解决方案2】:

根据您的问题:

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

可以使用the LINQ Dynamic Query Library 将 LINQ 查询中的字段名称指定为字符串。

您可以使用 DynamicQuery 库 针对任何 LINQ 数据提供者 (包括 LINQ to SQL、LINQ to 对象,LINQ to XML,LINQ to 实体、LINQ to SharePoint、LINQ to TerraServer 等)。而不是使用 语言运算符或类型安全的 lambda 扩展方法来构建你的 LINQ 查询,动态查询 库为您提供基于字符串的 您可以传递的扩展方法 任何字符串表达式。

顺便说一句,即使question 不完全相同,answer 也几乎相同。

【讨论】:

  • 一个答案;这里没有答案。
  • @Marc Gravell:不确定我是不是错过了一个语法笑话或其他什么(英语不是我的母语),但我链接到 a 特定答案,并且将其称为 the 答案(如我链接到的 the 答案中)我看不出有什么不对...
  • 我把它读作“这类问题的答案”,其中“the”(作为单数、定冠词)指的是“对这类问题的唯一可能的、理智的、合理的答案”。这并不重要,但在语言上,也许“this”会比“the”更清晰。
  • @Marc Gravell:好吧,如果我要给出“唯一可能的、理智的、明智的答案”,那显然是 42,对 ;)
猜你喜欢
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多