加入查询结果

时间:2015-06-26 11:21:55

标签: c# sql linq exception join

我有一个清单:

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;的常量值。只要   在此上下文中支持原始类型或枚举类型。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

您正在加入内存集合:qMyClassListIQueryable数据源。唯一的例外是因为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);

谢谢!