【问题标题】:Linq exception when join a list on a query result在查询结果中加入列表时出现 Linq 异常
【发布时间】:2015-09-13 08:02:02
【问题描述】:

我有一个清单:

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 存在,如果 AlternativeKey 中的前 4 个字符等于 MyClass.property1 或 MyClass.Property2,则选择行,否则选择如果 MainKey 中的前 4 个字符等于 MyClass.property1 或 MyClass.Property2,则为行。这是我的实现:

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);

在执行中,当我在结果元素上循环时,此查询引发此异常:

无法创建“MyTable+MyClass”类型的常量值。仅有的 在此上下文中支持原始类型或枚举类型。

我做错了什么?

【问题讨论】:

  • 尽量不要在查询中使用相等运算符 ("==")。

标签: c# sql linq exception join


【解决方案1】:

您正在加入 memory 集合: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 ...

【讨论】:

  • 如果MyClass 的列表已经在内存中,我怀疑删除.AsQueryable&lt;MyClass&gt;() 会清理这个问题。 (编辑:嗯,并且没有将其声明为可查询)
【解决方案2】:

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);

谢谢!

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多