在查询结果中加入列表时出现Linq异常

本文关键字:Linq 异常 列表 查询 结果 | 更新日期: 2023-09-27 17:59:48

我有一个列表:

List<MyClass> lstClass1;

其中MyClass有2个简单的字符串属性:

class MyClass
{
   public string property1 { get; set; }
   public string property2 { get; set; }
}

我在DB上有一个表MyTable要查询,其中有两个字符串类型的列:

MyTable
   column MainKey
   column AlternativeKey

对于我的脚本,我必须选择DB和列表的连接,规则如下:如果AlternativeKey存在,如果AlternateKey中的前4个字符等于MyClass.properties1或MyClass.Property2,则选择行;否则,如果MainKey中的前四个字符等于MySlass.properties1或MySlass.Property22,则选择该行。这是我的实现:

IQueryable<MyTable> source = getMyTable();
List<MyClass> lstClass1 = getListClass();
IQueryable<MyClass> qMyClassList = lstClass1.AsQueryable<MyClass>();
IQueryable<MyTable> selAlternative = from alt in source
                                     join cl1 in qMyClassList on
                                     alt.AlternativeKey.Substring(0, 4)
                                     equals cl1.property1
                                     join cl2 in qMyClassList on
                                     alt.AlternativeKey.Substring(0, 4)
                                     equals cl2.property2
                                     where alt.AlternativeKey != null && alt.AlternativeKey.Length >= 4
                                     select alt;
IQueryable<MyTable> selMain = from main in source
                                     join cl1 in qMyClassList on
                                     main.MainKey.Substring(0, 4)
                                     equals cl1.property1
                                     join cl2 in qMyClassList on
                                     main.MainKey.Substring(0, 4)
                                     equals cl2.property2
                                     where main.AlternativeKey == null && main.MainKey.Length >= 4
                                     select main;
source = alt.Union(main);

在执行中,当我在result元素上循环时,这个查询引发了这个异常:

无法创建"MyTable+MyClass"类型的常量值。只有在此上下文中支持基元类型或枚举类型。

我做错了什么?

在查询结果中加入列表时出现Linq异常

您正在加入内存集合:qMyClassListIQueryable数据源。出现异常是因为IQueryable LINQ提供程序无法将join转换为相关查询。

2个选项,您可以考虑:

选项1:您可以尝试在where中使用Contains而不是join。您的LINQ查询提供程序可能能够将您的查询解释为WHERE .. IN ('val1','val2'...)。所以对你来说,这看起来像这样:

var selAlternative = from alt in source 
                     where alt.AlternativeKey != null &&
                           property1List.Contains(alt.AlternativeKey.Substring(0, 4)) &&
                           property2List.Contains(alt.AlternativeKey.Substring(0, 4)) &&
                     select alt;

请记住,Contains仅适用于基元类型。在您的情况下,这似乎是一个string,所以它是好的。

选项2,如果您想保持加入状态,只需.ToList()您的source实例即可。如果您的源代码很大,这通常不是一个好主意,因为您将整个数据集加载到内存中,并且在内存中应用联接。):

var selAlternative = from alt in source.ToList()
                     join cl1 in qMyClassList on ...

Niels,选项1是一个很好的建议,但我必须这样过滤:

IQueryable<MyTable> source = getMyTable();
List<MyClass> lstClass1 = getListClass();
var property1List = (from prp in lstClass1 select prp.property1).Distinct();
var property2List = (from prp in lstClass1 select prp.property2).Distinct();
var selAlternative = from alt in source 
                     where alt.AlternativeKey != null &&
                     (property1List.Contains(alt.AlternativeKey.Substring(0, 4)) ||
                     property2List.Contains(alt.AlternativeKey.Substring(0, 4)))
                     select alt;
var selMain = from main in source 
                     where main.AlternativeKey == null &&
                     (property1List.Contains(main.MainKey.Substring(0, 4)) ||
                     property2List.Contains(main.MainKey.Substring(0, 4)))
                     select main;
source = alt.Union(main);

谢谢!