在查询结果中加入列表时出现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"类型的常量值。只有在此上下文中支持基元类型或枚举类型。
我做错了什么?
您正在加入内存集合:qMyClassList
到IQueryable
数据源。出现异常是因为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);
谢谢!