【问题标题】:LINQ to SQL Reflection in Select选择中的 LINQ to SQL 反射
【发布时间】:2017-10-19 19:36:15
【问题描述】:

我遇到了以下问题。我在 SQL 数据库中有一个如下所示的表:

|编号 |属性0 |属性 1 | attr2 |属性 3 | attr4 | attr5 |

所以,我想在 for 循环中从这个表中获取数据。

我已经创建了课程

public class Attribute{
    public int Id {get; set;}
    public string Description {get; set}
}

现在我想将表中的所有属性放到一个列表中

List<Attribute> attributeList = new List<Attribute>();
for(int i=0; i<6;i++)
{
    attributeList.Add((from a in db.Attributes
                  select new Attribute{
                      Id = a.Id,
                      Description = a.attr0}).First(); //How to use here i instead a fixed column name?
}

是否可以使用i,一次循环获取所有属性?

我试图使用反射,但编译器给了我一个错误,代码是:

for(int i=0; i<6;i++)
{
    attributeList.Add((from a in db.Attributes
                  select new Attribute{
                      Id = a.Id,
                      Description = a.GetType().GetProperty("attr"+i).GetValue(a,null))}).First();

更新: 错误是:

LINQ to Entities 无法识别方法 'System.Object GetValue(System.Object, System.Object[])' 方法,并且该方法无法转换为存储表达式。

【问题讨论】:

  • GetProperty("Attr" + i) 应为GetProperty("attr" + i)(小写字母a),因为列名以小写a 开头。我不知道这是否是错误,但看起来很可疑。
  • 我认为应用程序设计应该支持它的逻辑。您的逻辑需要属性的迭代 - 所以将其保存在数据库中,迭代将是最容易和最有效的。
  • @Twometer 不错。但是,OP 正在谈论“编译器”错误,而您提到的可能是运行时错误。
  • 问题可能是因为它是你的 linq 语句的一部分,它不能被翻译成数据库查询。先获取所有属性,再对结果集做反射

标签: c# .net linq reflection


【解决方案1】:

您正在尝试在“数据库”级别上使用反射,而 LinqToEntities 无法将其转换为 sql。

如果可能的话,这将导致您的查询针对同一行运行 6 次。

尝试先实例化您的数据库行类,然后对该对象使用反射

List<Attribute> attributeList = new List<Attribute>();
DbAttribute attrFirst = db.attributes.First();
for (int i = 0; i < 6; i++)
{
    attributeList.Add(new Attribute {
        Id = attrFirst.Id,
        Description =(string)attrFirst.GetType().GetProperty("attr" + i).GetValue(attrFirst)
    });
}

【讨论】:

  • 太棒了!这对我有用!谢谢!
【解决方案2】:

GetValue 无法转换为 T-SQL,Linq to Entities 无法识别。您可以查看此答案以获取更多详细信息https://stackoverflow.com/a/41802414/2946329

试试这个解决方案。这将为您提供所需的内容:

var first = (from a in db.Attributes select a).FirstOrDefault();
List<Attribute> t = first?.GetType().GetProperties()
  .Select(c => new Attribute { Id = first.Id ,  Description = c.GetValue(first).ToString()})
  .ToList();

通过这种方法,使用 Linq to Objects 对内存中已经存在的数据执行任何进一步的操作,您不会再收到此错误。此外,通过使用 LINQ,您不再需要 for 循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多