1

我使用 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)

自身内。我得到错误:

"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."

任何想法将不胜感激。

4

3 回答 3

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 子句之前将类别数据作为对象集合检索:

dc.Categories.ToList().Where(Function(x) x.ParentCategory Is ParentCategory)

显然,这可能意味着通过网络传递更多数据,因此第一种方法更可取。

于 2013-06-25T15:46:54.757 回答
1

实体框架不知道如何将类转移到实际的 SQL 中。如果您改为在 where 子句中使用 CategoryId,它应该可以工作。我使用 C#,所以希望以下内容有意义:

For Each c As Category In dc.Categories.Where(Function(x) x.ParentCategory.CategoryId = ParentCategory.CategoryId).ToList
于 2013-06-25T15:49:11.587 回答
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 对象本身。

于 2013-06-26T08:32:11.733 回答