VB.NET LINQ to DataSet (альтернатива SQL 'LEFT OUTER JOIN') - PullRequest
0 голосов
/ 12 мая 2018

Я хотел бы объединить две таблицы данных и создать третью из результатов.В результате DataTable должен иметь три столбца:

  • ID
  • Имя
  • YearOfBirth

Параметры моей компиляции:

  • Опция явная: Вкл.
  • Опция строгая: Вкл.
  • Сравнение опций: Двоичные
  • Вывод опции: Выкл.

    Dim dr As DataRow
    
    REM Dt1
    Dim Dt1 As New DataTable
    Dt1.Columns.Add("ID", GetType(Integer))
    Dt1.Columns.Add("Name", GetType(String))
    
    dr = Dt1.NewRow
    dr("ID") = 1
    dr("Name") = "Peter"
    Dt1.Rows.Add(dr)
    
    dr = Dt1.NewRow
    dr("ID") = 2
    dr("Name") = "Anna"
    Dt1.Rows.Add(dr)
    
    dr = Dt1.NewRow
    dr("ID") = 3
    dr("Name") = "John"
    Dt1.Rows.Add(dr)
    REM End Dt1
    
    REM Dt2
    Dim Dt2 As New DataTable
    Dt2.Columns.Add("ID", GetType(Integer))
    Dt2.Columns.Add("YearOfBirth", GetType(Integer))
    
    dr = Dt2.NewRow
    dr("ID") = 1
    dr("YearOfBirth") = 1970
    Dt2.Rows.Add(dr)
    
    dr = Dt2.NewRow
    dr("ID") = 2
    dr("YearOfBirth") = 1980
    Dt2.Rows.Add(dr)
    REM End Dt2
    
    Dim Dt3 As New DataTable
    
    Dim query As IEnumerable(Of DataRow) = From dr1 In Dt1.AsEnumerable()
                                           Group Join dr2 In Dt2.AsEnumerable()
                                           On dr1.Field(Of Integer)("ID") Equals dr2.Field(Of Integer)("ID")
                                           Into joined = Group
                                           From j In joined.DefaultIfEmpty()
                                           Select New With
                                               {
                                               .ID = dr1.Field(Of Integer)("ID"),
                                               .Name = dr1.Field(Of String)("Name"),
                                               .YearOfBirth = j.Field(Of Integer)("YearOfBirth")
                                               }
    
    
    Dt3 = query.CopyToDataTable
    

Но я получаю сообщение об ошибке в редакторе (VS 2017):

"Ошибка BC36754:« IEnumerable (анонимного типа: ID как целое число, имя как строка, годOfBirth как целое число) »не можетпреобразовать в «IEnumerable (Of DataRow)», поскольку «анонимный тип: ID как целое число, имя как строка, год как целое число как год» не является производным от «DataRow», как требуется для универсального параметра «T» Out в «Interface»IEnumerable (Of Out T) '. "

1 Ответ

0 голосов
/ 14 мая 2018

Select New без указания имени класса в качестве результата запроса будет возвращать анонимный тип (например, IEnumerable(Of AnonymousType)) и CopyToDataTable() исключение, поскольку IEnumerable(Of AnonymousType) не может быть преобразовано непосредственно в IEnumerable(Of DataRow).

Следовательно, вам необходимо преобразовать анонимный тип в DataRow, используя дополнительный метод Select, который перебирает содержимое IEnumerable(Of AnonymousType) и возвращает DataRow с DataTable.NewRow() (используя подготовленный DataTable, который включает имена столбцов как результирующий набор):

' joined DataTable columns
Dim JoinedDT As New DataTable
JoinedDT.Columns.Add("ID", GetType(Integer))
JoinedDT.Columns.Add("Name", GetType(String))
JoinedDT.Columns.Add("YearOfBirth", GetType(Integer))

' other stuff

Dim query As IEnumerable(Of DataRow) = (From dr1 In Dt1.AsEnumerable() _
                                       Group Join dr2 In Dt2.AsEnumerable() _
                                       On dr1.Field(Of Integer)("ID") Equals dr2.Field(Of Integer)("ID") _
                                       Into joined = Group _
                                       From j In joined.DefaultIfEmpty() _
                                       Select New With
                                       {
                                           .ID = dr1.Field(Of Integer)("ID"),
                                           .Name = dr1.Field(Of String)("Name"),
                                           .YearOfBirth = If(j IsNot Nothing, j.Field(Of Integer)("YearOfBirth"), 0)
                                       }).Select(Function(r)
                                           ' use `DataTable.NewRow` here
                                           Dim row As DataRow = JoinedDT.NewRow()
                                           row("ID") = r.ID
                                           row("Name") = r.Name
                                           row("YearOfBirth") = r.YearOfBirth
                                           Return row
                                       End Function)

Dt3 = query.CopyToDataTable()

Справка:

Получить linq для возврата IEnumerable результат (версия C #)

...