1

EF Codefirst を使用して VB.net WinForms プログラムとデータベースを作成しました。テーブルの 1 つである "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 でエンティティに解決できない式が含まれています。

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

これは、2 つのオブジェクトの型ではなくキーを比較することで回避できます。

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)

明らかに、これはより多くのデータをネットワーク経由で渡すことを意味する可能性があるため、最初のアプローチが推奨されます。

于 2013-06-25T15:46:54.757 に答える
1

Entity Frameworks は、クラスを実際の 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) 親がある場合 (以下の解決策) の 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

Category オブジェクト自体ではなく、ParentCategoryId だけを再帰関数に渡すことができることはわかっています。

于 2013-06-26T08:32:11.733 に答える