我使用EF Codefirst创建了一个VB.net WinForms程序和一个数据库。在其中一个表“Categories”中,有一个名为“ParentCategory_CategoryId”的列,它是该特定类别的父类别(nb可以为NULL)。这允许我为子类别设置无限量的嵌套。到目前为止,这么好(下面的类别定义):
Public Class Category
Public Property CategoryId As Integer
Public Property CategoryName As String
Public Overridable Property ChildCategories As List(Of Category)
Public Overridable Property ParentCategory As Category
End Class
当我尝试使用此数据填充TreeView控件时出现问题。我的目的是递归遍历类别,并为每个类别添加一个TreeNode,并为每个子类别添加一个子节点。 VB代码如下:
Private Sub Categories_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Create new data context
Dim dc As New MyContext
' Call the recursive function once with Parent category as nothing
LoadNodesOntoTreeview(dc, Nothing, Nothing)
End Sub
Public Sub LoadNodesOntoTreeview(dc As MyContext, Optional ParentCategory As Category = Nothing, Optional ByRef ParentNode As TreeNode = Nothing)
Try
For Each c As Category In dc.Categories.Where(Function(x) x.ParentCategory Is ParentCategory).ToList
Dim n As New TreeNode With {.Text = c.CategoryName}
LoadNodesOntoTreeview(dc, c, n)
If ParentNode Is Nothing Then
TreeView1.Nodes.Add(n)
Else
ParentNode.Nodes.Add(n)
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
对于第一次迭代(ParentCategory = Nothing),这可以正常工作,但调用时会出现问题
LoadNodesOntoTreeview(dc, c, n)
在iteslf内。我收到错误:
"Unable to create a constant value of
type 'System.Data.Entity.DynamicProxies.Category_D3161C0FA58DECDDCD3237
36A77B49BF9AC13F6AB1D9C56D7946173054210834'. Only primitive types or
enumeration types are supported in this context."
非常感谢任何想法。
答案 0 :(得分:1)
查询中的Where子句包含Linq to Entities无法解析的表达式:
dc.Categories.Where(Function(x) x.ParentCategory Is ParentCategory)
您可以通过比较两个对象的键而不是它们的类型来避免这种情况:
dc.Categories.Where(Function(x) x.ParentCategory.CategoryId = ParentCategory.CategoryId)
或者,您可以使用Linq to Objects运行此查询。为此,您需要在评估where子句之前将Categories数据检索为对象集合:
dc.Categories.ToList().Where(Function(x) x.ParentCategory Is ParentCategory)
显然,这可能意味着通过线路传递更多数据,因此第一种方法更可取。
答案 1 :(得分:1)
实体框架不知道如何将类转移到实际的SQL。如果您在where子句中使用CategoryId,它应该可以工作。我使用C#,所以希望以下是有道理的:
For Each c As Category In dc.Categories.Where(Function(x) x.ParentCategory.CategoryId = ParentCategory.CategoryId).ToList
答案 2 :(得分:0)
谢谢大家,已经解决了这个问题,但我不得不分开两个案例,其中类别有1)没有父母和2)父母(下面的解决方案)。
我也搬家了
Dim dc as new myContext
在递归函数中,因为我生成了一个额外的错误(数据上下文在关闭之前无法重复使用 - 显然!)。
Private Sub Categories_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadNodesOntoTreeview()
End Sub
Public Sub LoadNodesOntoTreeview(Optional ParentCategory As Category = Nothing, Optional ByRef ParentNode As TreeNode = Nothing)
Try
Dim dc As New MyContext
If ParentCategory Is Nothing Then
For Each c As Category In dc.Categories.Where(Function(x) x.ParentCategory Is Nothing)
Dim n As New TreeNode With {.Text = c.CategoryName}
LoadNodesOntoTreeview(c, n)
TreeView1.Nodes.Add(n)
Next
Else
For Each c As Category In dc.Categories.Where(Function(x) x.ParentCategory.CategoryId = ParentCategory.CategoryId).ToList
Dim n As New TreeNode With {.Text = c.CategoryName}
LoadNodesOntoTreeview(c, n)
ParentNode.Nodes.Add(n)
Next
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
我知道我只能将ParentCategoryId传递给递归函数而不是Category对象本身。