powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
5 сообщений из 5, страница 1 из 1
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
    #39154139
Иван215
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нашел я статью на сайте Microsoft с чрезвычайно полезной вещью.

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

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

Код: vbnet
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



и добвить расширения методов:

Код: vbnet
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.

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

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

Мой код:


Код: vbnet
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()
...
Рейтинг: 0 / 0
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
    #39154144
Иван215
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
На всякий случай. У меня установлены: NET 4.0 и VS2010 Ultimate.

После добавления указанного кода в свое приложение пришлось добавить ссылки:

System.Reflection
System.Runtime.CompilerServices
...
Рейтинг: 0 / 0
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
    #39158351
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иван215,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public static class FuckSyntax {

public static bool isEnumerableT(object variable)
{
  if (variable != null)
  {
    if (variable.GetType().GetInterfaces().Any(
            i => i.IsGenericType &&
            i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
    {
        return true;
    }
  }
  return false;
}

public static DataTable CopyToDataTable<T>(this IEnumerable<T> row)
{
	Console.WriteLine("Extension Called");
	return new DataTable();
}

}



1я фунция тестирует, является ли некая хрень шаблоном IEnumerable (пригодилось тестировать, что сгенерилось в анонимном типе)

2я пример как подсунуть свою ф-цию как метод расширения.
на шарпе для этого используется ключевою слово this, на ВБ - я не знаю см.доку
...
Рейтинг: 0 / 0
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
    #39158357
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another.
...
Рейтинг: 0 / 0
Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
    #39187045
Gc2112
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иван215,
неправильный набор параметров - в первом случае должен передавася один, во втором 3.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Реализация метода CopyToDataTable<T>, если универсальный тип T не является DataRow - LINQ
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]