我正在尝试生成一个网格,最终用户可以使用多个输入来过滤数据。
为此,我尝试按如下方式过滤初始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实现它。
答案 0 :(得分:1)
这是Linq Expression中闭包中捕获的问题。
在英语中,这意味着您正试图将CLng(cboProperty.EditValue)
传递给Linq Expression。这是合法的。但是,当Linq to Entity Framework查看它时,它无法将其转换为SQL。该表达式包含:
可怜的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 Expression转换为函数调用。
我个人对于Lambda表达式如何与Lambda函数具有相同的语法有两种想法,导致这些例外。
BTW我更喜欢这种形式的查询...
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重构为已编译的查询。