0

我正在尝试生成一个网格,最终用户可以使用多个输入过滤数据。

为此,我尝试过滤初始 LINQ to Entities 对象,如下所示:

Dim servhist As IQueryable(Of servicesHistory) = db.servicesHistories

If cboProperty.EditValue <> Nothing Then
    servhist = servhist.Where(Function(p) p.propID = CLng(cboProperty.EditValue))
End If

grdServHist.DataSource = servhist.ToList()

但是,当我尝试过滤查询时,在尝试枚举集合时收到以下错误消息:“无法创建类型为 'System.Object' 的常量值。在此上下文中仅支持原始类型或枚举类型。”

我不知所措。我已经使用 C# 解决了这个问题,但不幸的是无法使用 VB。

4

1 回答 1

1

这是 Linq 表达式中闭包中的捕获问题。

在英语中,这意味着您正在尝试传递CLng(cboProperty.EditValue)一个 Linq 表达式。这是合法的。但是,当 Linq to Entity Framework 看到它时,它无法将其转换为 SQL。该表达式包含:

  1. 一个 .net 类(我怀疑很可能是一个 winform 控件)
  2. .net 类的属性调用
  3. 对 .net 类结果的 .net 转换调用。

可怜的 Linq2EF 无法弄清楚这些东西!然而,这将起作用。

Dim servhist As IQueryable(Of servicesHistory) = db.servicesHistories

If cboProperty.EditValue <> Nothing Then
    Dim editValue = CLng(cboProperty.EditValue)
    servhist = servhist.Where(Function(p) p.propID = editValue)
End If

grdServHist.DataSource = servhist.ToList()

现在这看起来完全一样。但是,如果您问 Linq Ninja,他们会告诉您两者非常不同,因为我已将CLng(cboProperty.EditValue)Linq 表达式转换为函数调用。

我个人对 Lambda 表达式如何具有与 Lambda 函数相同的语法有两种看法,从而导致这些异常。

顺便说一句,我更喜欢这种形式的查询...

Dim editValue = CLng(cboProperty.EditValue)
Dim servhist As IQueryable(Of servicesHistory) = _
    db.servicesHistories.Where(Function(p) p.propID = editValue or editValue is Nothing)
grdServHist.DataSource = servhist.ToList()

这允许您随后将 IQueryable 重构为已编译的查询。

于 2013-05-14T05:16:26.627 回答