我有一个清单:
List<MyClass> lstClass1;
MyClass有两个简单的字符串属性:
class MyClass
{
public string property1 { get; set; }
public string property2 { get; set; }
}
我有一个关于DB,MyTable的表来查询,其中有两个字符串类型列:
MyTable
column MainKey
column AlternativeKey
对于我的脚本,我必须选择DB和列表的连接,并使用以下规则:如果AlternativeKey存在,如果AlternativeKey中的前4个字符等于MyClass.property1或MyClass.Property2,则选择该行,否则选择如果MainKey中的前4个字符等于MyClass.property1或MyClass.Property2,则为row。这是我的实施:
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);
在执行时,当我在结果元素上循环时,此查询引发此异常:
无法创建类型为&#39; MyTable + MyClass&#39;的常量值。只要 在此上下文中支持原始类型或枚举类型。
我做错了什么?
答案 0 :(得分:1)
您正在加入内存集合:qMyClassList
到IQueryable
数据源。唯一的例外是因为IQueryable LINQ Provider无法将join
翻译成相关查询。
2个选项,您可以考虑:
选项1 :您可以尝试使用Contains
中的where
代替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 ...
答案 1 :(得分:0)
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);
谢谢!