Как заполнить коллекцию из нескольких DataTables - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь заполнить коллекцию, которая состоит из двух моделей из двух наборов данных одновременно. Я могу заполнить одну, но не могу сделать для второй. Мой пример прояснит далее,

 'Employee Class
    Public Class Employee
      Public Property ID As Integer
      Public Property Name as String
      Public Property Details() as DetailsCol
    End Class

Sub New(ord as Datarow)
  Me.ID= ord("ID")
  Me.Name=ord("Name")
End Sub

Public Class DetailsCol
    Inherits List(Of Details)
    Sub New()

    End Sub
End Class

 'Details class
Public Class Details
  Public Property Address As String
  Public Property Salary as Double
End Class

Sub New(ord as Datarow)
  Me.Address= ord("Address")
  Me.Salary=ord("Salary")
End Sub

'Main collection where DB call need to set both the collection
Public Class EmployeeCol
    Inherits List(Of Employee)

    Sub New()

    End Sub

    Sub New(ByVal EMP_ID As Integer)
        Dim ds As DataSet = Helper.GO_GET_DisplayEmployee(EMP_ID)
        If Not IsNothing(ds) AndAlso Not IsNothing(ds.Tables) AndAlso ds.Tables.Count > 0 Then
            'Populating Employee 
            For Each dr As DataRow In ds.Tables(0).Rows
                Dim empObj As Employee = New Employee(dr)
                Me.Add(empObj)
            Next

            'TO DO: Trying to populate Details model but not finding way to do
            For Each dr As DataRow In ds.Tables(1).Rows

            Next
        End If

    End Sub

End Class

Редактировать **

Спасибо, я пытаюсь переписать на основе предложения. Я могу получить коллекцию сотрудников для всех записей, но коллекция пользователей пуста.

Dim rtnContent As New List(Of Employee)

        Dim ds As DataSet = Helper.GO_GET_DisplayDetails(emp_id)
        If Not IsNothing(ds) AndAlso Not IsNothing(ds.Tables) AndAlso ds.Tables.Count > 0 Then
            ds.Tables(0).TableName = "employee"
            ds.Tables(1).TableName = "users"

            ds.Relations.Add(New DataRelation("griddisplay", ds.Tables("employee").Columns("emp_id"), ds.Tables("users").Columns("emp_id")))

            rtnContent = ds.GetAccessor(Of Employee)("employee")
        End If

1 Ответ

1 голос
/ 20 марта 2020

Существует множество проблем с этим кодом, но для решения вашей конкретной проблемы c вы должны начать с того, что в вашем DataSet есть DataRelation между двумя DataTables. Затем вы можете сразу получить все дочерние строки для любой родительской строки и родительскую строку для любой дочерней строки. В качестве общего примера вы можете создать такой DataSet, например:

Dim data As New DataSet
Dim parentTable = data.Tables.Add("Parent")
Dim childTable = data.Tables.Add("Child")

With parentTable.Columns
    parentTable.PrimaryKey = {.Add("ParentId", GetType(Integer))}
    .Add("ParentName", GetType(String))
End With

With childTable.Columns
    childTable.PrimaryKey = {.Add("ChildId", GetType(Integer))}
    .Add("ParentId", GetType(Integer))
    .Add("ChildName", GetType(String))
End With

data.Relations.Add("ParentChild",
                   parentTable.Columns("ParentId"),
                   childTable.Columns("ParentId"))

Затем вы можете получить доступ к дочерним строкам, указав c для каждой родительской строки, например:

For Each parentRow As DataRow In parentTable.Rows
    For Each childRow As DataRow In parentRow.GetChildRows("ParentChild")
        '...
    Next
Next

В вашем случае это означает, что вы можете / должны изменить конструктор в вашем EmployeeCol классе на что-то вроде этого:

Sub New(employeeId As Integer)
    Dim data = Helper.GO_GET_DisplayEmployee(employeeId)

    If data?.Tables.Count = 2 Then
        For Each employeeRow As DataRow In data.Tables("Employee").Rows
            Dim detailsList As New List(Of Details)

            For Each detailsRow In employeeRow.GetChildRows("EmployeeDetails")
                detailsList.Add(New Details(detailsRow))
            Next

            Me.Add(New Employee(employeeRow) With {.Details = detailsList.ToArray()})
        Next
    End If
End Sub

РЕДАКТИРОВАТЬ:

Одна из проблем, с которыми я столкнулся Ранее мы ссылались на тот факт, что внутри типов вашей модели есть код ADO. NET. Это плохой дизайн, но, если вы собираетесь это сделать, вы можете сделать это гораздо более чисто, например:

Imports System.Collections.ObjectModel

Public Class Details

    Public Property Address As String
    Public Property Salary As Decimal

    Public Sub New(row As DataRow)
        Address = row.Field(Of String)(NameOf(Address))
        Salary = row.Field(Of Decimal)(NameOf(Salary))
    End Sub

End Class

Public Class DetailsCollection
    Inherits Collection(Of Details)

    Public Sub New(table As DataTable)
        Me.New(table.Rows.Cast(Of DataRow)())
    End Sub

    Public Sub New(rows As IEnumerable(Of DataRow))
        For Each row In rows
            Items.Add(New Details(row))
        Next
    End Sub

End Class

Public Class Employee

    Public Property Id As Integer
    Public Property Name As String
    Public ReadOnly Property Details As DetailsCollection

    Public Sub New(row As DataRow)
        Id = row.Field(Of Integer)(NameOf(Id))
        Name = row.Field(Of String)(NameOf(Name))
        Details = New DetailsCollection(row.GetChildRows($"{NameOf(Employee)}{NameOf(Details)}"))
    End Sub

End Class

Public Class EmployeeCollection
    Inherits Collection(Of Employee)

    Public Sub New(employeeId As Integer)
        Me.New(Helper.GO_GET_DisplayEmployee(employeeId).Tables(NameOf(Employee)))
    End Sub

    Public Sub New(table As DataTable)
        Me.New(table.Rows.Cast(Of DataRow)())
    End Sub

    Public Sub New(rows As IEnumerable(Of DataRow))
        For Each row In rows
            Items.Add(New Employee(row))
        Next
    End Sub

End Class

Множество улучшений по сравнению с вашей структурой кода там, но я все равно напишу свой код несколько иначе, если начинать с нуля. Следует отметить, что для DataSet или DataTables нет нулевой проверки. Если бы это был я, я бы удостоверился, что метод, который получает данные, всегда возвращает DataSet, и он всегда содержит два DataTables. Если в них нет данных, пусть будет так, и в итоге вы получите пустой EmployeeCollection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...