Форум программистов, компьютерный форум, киберфорум
LINQ
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
21 / 22 / 10
Регистрация: 03.07.2014
Сообщений: 398

Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow

21.01.2016, 01:14. Показов 1028. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нашел я статью на сайте Microsoft с чрезвычайно полезной вещью.

Как реализовать метод CopyToDataTable<T>, если универсальный тип T не является DataRow

Заявлено, что если в приложение добавить класс

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
Public Class ObjectShredder(Of T)
    ' Fields
    Private _fi As FieldInfo()
    Private _ordinalMap As Dictionary(Of String, Integer)
    Private _pi As PropertyInfo()
    Private _type As Type
 
    ' Constructor 
    Public Sub New()
        Me._type = GetType(T)
        Me._fi = Me._type.GetFields
        Me._pi = Me._type.GetProperties
        Me._ordinalMap = New Dictionary(Of String, Integer)
    End Sub
 
    Public Function ShredObject(ByVal table As DataTable, ByVal instance As T) As Object()
        Dim fi As FieldInfo() = Me._fi
        Dim pi As PropertyInfo() = Me._pi
        If (Not instance.GetType Is GetType(T)) Then
            ' If the instance is derived from T, extend the table schema
            ' and get the properties and fields.
            Me.ExtendTable(table, instance.GetType)
            fi = instance.GetType.GetFields
            pi = instance.GetType.GetProperties
        End If
 
        ' Add the property and field values of the instance to an array.
        Dim values As Object() = New Object(table.Columns.Count - 1) {}
        Dim f As FieldInfo
        For Each f In fi
            values(Me._ordinalMap.Item(f.Name)) = f.GetValue(instance)
        Next
        Dim p As PropertyInfo
        For Each p In pi
            values(Me._ordinalMap.Item(p.Name)) = p.GetValue(instance, Nothing)
        Next
 
        ' Return the property and field values of the instance.
        Return values
    End Function
 
 
    ' Summary:           Loads a DataTable from a sequence of objects.
    ' source parameter:  The sequence of objects to load into the DataTable.</param>
    ' table parameter:   The input table. The schema of the table must match that 
    '                    the type T.  If the table is null, a new table is created  
    '                    with a schema created from the public properties and fields 
    '                    of the type T.
    ' options parameter: Specifies how values from the source sequence will be applied to 
    '                    existing rows in the table.
    ' Returns:           A DataTable created from the source sequence.
 
    Public Function Shred(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
 
        ' Load the table from the scalar sequence if T is a primitive type.
        If GetType(T).IsPrimitive Then
            Return Me.ShredPrimitive(source, table, options)
        End If
 
        ' Create a new table if the input table is null.
        If (table Is Nothing) Then
            table = New DataTable(GetType(T).Name)
        End If
 
        ' Initialize the ordinal map and extend the table schema based on type T.
        table = Me.ExtendTable(table, GetType(T))
 
        ' Enumerate the source sequence and load the object values into rows.
        table.BeginLoadData()
        Using e As IEnumerator(Of T) = source.GetEnumerator
            Do While e.MoveNext
                If options.HasValue Then
                    table.LoadDataRow(Me.ShredObject(table, e.Current), options.Value)
                Else
                    table.LoadDataRow(Me.ShredObject(table, e.Current), True)
                End If
            Loop
        End Using
        table.EndLoadData()
 
        ' Return the table.
        Return table
    End Function
 
 
    Public Function ShredPrimitive(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
        ' Create a new table if the input table is null.
        If (table Is Nothing) Then
            table = New DataTable(GetType(T).Name)
        End If
        If Not table.Columns.Contains("Value") Then
            table.Columns.Add("Value", GetType(T))
        End If
 
        ' Enumerate the source sequence and load the scalar values into rows.
        table.BeginLoadData()
        Using e As IEnumerator(Of T) = source.GetEnumerator
            Dim values As Object() = New Object(table.Columns.Count - 1) {}
            Do While e.MoveNext
                values(table.Columns.Item("Value").Ordinal) = e.Current
                If options.HasValue Then
                    table.LoadDataRow(values, options.Value)
                Else
                    table.LoadDataRow(values, True)
                End If
            Loop
        End Using
        table.EndLoadData()
 
        ' Return the table.
        Return table
    End Function
 
    Public Function ExtendTable(ByVal table As DataTable, ByVal type As Type) As DataTable
        ' Extend the table schema if the input table was null or if the value 
        ' in the sequence is derived from type T.
        Dim f As FieldInfo
        Dim p As PropertyInfo
 
        For Each f In type.GetFields
            If Not Me._ordinalMap.ContainsKey(f.Name) Then
                Dim dc As DataColumn
 
                ' Add the field as a column in the table if it doesn't exist
                ' already.
                dc = IIf(table.Columns.Contains(f.Name), table.Columns.Item(f.Name), table.Columns.Add(f.Name, f.FieldType))
 
                ' Add the field to the ordinal map.
                Me._ordinalMap.Add(f.Name, dc.Ordinal)
            End If
 
        Next
 
        For Each p In type.GetProperties
            If Not Me._ordinalMap.ContainsKey(p.Name) Then
                ' Add the property as a column in the table if it doesn't exist
                ' already.
                Dim dc As DataColumn
                dc = IIf(table.Columns.Contains(p.Name), table.Columns.Item(p.Name), table.Columns.Add(p.Name, p.PropertyType))
 
                ' Add the property to the ordinal map.
                Me._ordinalMap.Add(p.Name, dc.Ordinal)
            End If
        Next
 
        ' Return the table.
        Return table
    End Function
 
End Class
и модуль

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
Public Module CustomLINQtoDataSetMethods
    <Extension()> _
    Public Function CopyToDataTable(Of T)(ByVal source As IEnumerable(Of T)) As DataTable
        Return New ObjectShredder(Of T)().Shred(source, Nothing, Nothing)
    End Function
 
    <Extension()> _
    Public Function CopyToDataTable(Of T)(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
        Return New ObjectShredder(Of T)().Shred(source, table, options)
    End Function
 
End Module
То можно результат запроса LINQ копировать в таблицу DataTable

VB.NET
1
2
3
4
5
6
7
Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2001, 8, 1) _
    Select order
 
' Create a table from the query.
Dim boundTable As DataTable = query.CopyToDataTable()

Попробовал я это сделать в своем приложении, но сорвалась конфетка.

Ошибка компиляции. Смотри миниатюру. Может кто-то этим пользовался и может подсказать. Очень полезная вещь вроде.

Мой код:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'=================================================================================================='
'                                      Поиск дублей по ITID                                                                                                             '
'=================================================================================================='
 
        Dim Itid_DBL = _
            From R1 In T1.AsEnumerable() _
            Join R2 In T2.AsEnumerable() On _
                R1.Field(Of String)("ITID") Equals _
                R2.Field(Of String)("ITID") _
                                Where (CLng(R1!ID) <> CLng(R2!ID)) And _
                  (((CInt(R1!YML) <= CInt(R2!YML)) And (CInt(R2!YML) <= CInt(IIf(CInt(R1!YMH) = 0, 9999, CInt(R1!YMH))))) Or _
                   ((CInt(R1!YML) <= CInt(IIf(CInt(R2!YMH) = 0, 9999, CInt(R2!YMH)))) And (CInt(IIf(CInt(R2!YMH) = 0, 9999, CInt(R2!YMH))) <= CInt(IIf(CInt(R1!YMH) = 0, 9999, CInt(R1!YMH))))) Or _
                   ((CInt(R2!YML) <= CInt(R1!YML)) And (CInt(R1!YML) <= CInt(IIf(CInt(R2!YMH) = 0, 9999, CInt(R2!YMH))))) Or _
                   ((CInt(R2!YML) <= CInt(IIf(CInt(R1!YMH) = 0, 9999, CInt(R1!YMH)))) And (CInt(IIf(CInt(R1!YMH) = 0, 9999, CInt(R1!YMH))) <= CInt(IIf(CInt(R2!YMH) = 0, 9999, CInt(R2!YMH)))))) _
            Select New With { _
                .ID1 = R1.Field(Of Long)("ID"), _
                .ID2 = R2.Field(Of Long)("ID"), _
                .ITID1 = R1.Field(Of String)("ITID"), _
                .ITID2 = R2.Field(Of String)("ITID"), _
                .YML1 = R1.Field(Of Decimal)("YML"), _
                .YML2 = R2.Field(Of Decimal)("YML"), _
                .YMH1 = R1.Field(Of Decimal)("YMH"), _
                .YMH2 = R2.Field(Of Decimal)("YMH")}
 
        Dim IDBL As New DataTable
        IDBL = Itid_DBL.CopyToDataTable()
Миниатюры
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow  
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.01.2016, 01:14
Ответы с готовыми решениями:

Универсальный указатель или универсальный скалярный тип
Здравствуйте! Помогите, пожалуйста написать программу: требуется написать универсальный скалярный тип данных без использования шаблонов....

Привести один тип к другому. Тип универсальный, параметризируется другими типами
Доброго времени суток! Прошу помощи, что-то туплю. Под вечер или вообще :) Пытаюсь привести один тип к другому. Тип универсальный,...

Если число является простым, то функция возвращает true, если не является false
Напишите функцию, получающую целое число N(&gt;0). Если оно является простым, то функция возвращает true, если не является false. #include...

5
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18240 / 14154 / 5366
Регистрация: 17.03.2014
Сообщений: 28,841
Записей в блоге: 1
21.01.2016, 20:17
Ivan215, у меня данный код компилируется без ошибок. Какую версию VB.NET/VS ты используешь?
0
21 / 22 / 10
Регистрация: 03.07.2014
Сообщений: 398
21.01.2016, 21:30  [ТС]
Net 4.0, VS2010 Ultimate. Пришлось перед использованием несколько ссылок добавить в проект - может добавил не то?

Не помню точно, по моему добавил

System.Reflection
System.Runtime.CompilerServices

без них в классе ObjectShredder были нераспознаваемые типы - FieldInfo и другие.
0
21 / 22 / 10
Регистрация: 03.07.2014
Сообщений: 398
23.01.2016, 23:43  [ТС]
И тишина...
0
Заблокирован
23.01.2016, 23:50
Ivan215, а вы добавляйте обращение, так придет уведомление:

Code
1
[nick]<тут ник>[/nick]
Призовем OwenGlendower
0
21 / 22 / 10
Регистрация: 03.07.2014
Сообщений: 398
24.01.2016, 03:58  [ТС]
Так чего добавлять-то? Господин модератор интересовался какая версия у меня Net и VS. Я так надеялся, что он что-нибуль прояснит, а в ответ тишина.

Я новичок в LINQ-е и вообще в DOTNET-е, а этот Class ObjectShredder такой навороченный, очень многие языковые конструкции ну вообще ни бум-бум. Одно мне странно - расширение метода вызывается БЕЗ ПАРАМЕТРОВ:

VB.NET
1
Dim boundTable As DataTable = query.CopyToDataTable()
а в описании расширений метода CopyToDataTable - куча параметров. Несоответствие какое-то.

Почитал я и про расширения типов - вроде все корректно (да и как иначе - вроде сайт Microsoft - хоть и малоуважаемая компания - но ошибок быть не должно).

Можно конечно обойтись и без этой конфетки - но как-то тоскливо каждый раз все вручную делать:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            Dim IDBL As New DataTable
 
            IDBL.Columns.Add("ID1", GetType(Long))
            IDBL.Columns.Add("ID2", GetType(Long))
            IDBL.Columns.Add("ITID1", GetType(String))
            IDBL.Columns.Add("ITID2", GetType(String))
            IDBL.Columns.Add("YML1", GetType(Decimal))
            IDBL.Columns.Add("YMH1", GetType(Decimal))
            IDBL.Columns.Add("YML2", GetType(Decimal))
            IDBL.Columns.Add("YMH2", GetType(Decimal))
 
For Each RR In Itid_DBL
      IDBL.Rows.Add(RR.ID1, RR.ID2, RR.ITID1, RR.ITID2, RR.YML1, RR.YMH1, RR.YML2, RR.YMH2)
Next
Добавлено через 7 минут
Да не прогневается господин модератор (OwenGlendower), но я по теме

Странное описание свойства Form.KeyPreview

до сих пор жду ответа (с 19 декабря 2015 года)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.01.2016, 03:58
Помогаю со студенческими работами здесь

Универсальный вызов метода через указатель на объект
Никак не могу найти универсальную конструкцию, которая позволяла бы вызывать любой метод класс, с любыми параметрами через указатель на...

Нужно перевести программу из паскаль в делфи . Сама программа этот реализация метода гауса и метода зейделя
Это все в паскале сделано. В программе идет в начале описание меня а аотом сама подпрограмма реализации этих методов. В делфи надо сделать...

Написать универсальный скалярный тип с использованием класса
Дали такое вот задание, как писать не понятно. Смысл задачи в том, что имеется некоторая переменная, например инт и он хранит значение 5....

While4°. Дано целое число N (> 0). Если оно является степенью числа 3, то вывести true, если не является — вывести false.
While. Дано целое число N (&gt; 0). Если оно является степенью числа 3, то вывести true, если не является — вывести false.

Дано целое число N(>0). Если оно является степенью числа 3, то вывести TRUE, если не является-вывести FALSE.
Дано целое число N(&gt;0). Если оно является степенью числа 3, то вывести TRUE, если не является-вывести FALSE. Я не могу записать её с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru