CONVERTER UM RESULTADO DE LINQ TO SQL EM DATASET

ANGELOATA 17/04/2013 15:52:36
#422073
Pessoal

Alguem tem ideia de como faço para pegar um resultado de linq to SQL e transforma-lo em um dataset?

Att.

Angelo
MJAC 17/04/2013 22:36:19
#422103
Resposta escolhida
Você precisa fazer [Ô]shallow copy[Ô] como infelizmente o VB não possui método nativo para isso como o C#, montei a classe genérica ObjectShredder usando Reflection e criei Extensions no módulo DataSetLinqOperators, logo abaixo posto estes códigos, para usar é algo como :

  
[ô] Carregar em um novo DataTable
Dim query1 = From i In tabela_obj Where i.Preco > 9.99 Order By i.Nome
Dim table1 As DataTable = query1.CopyToDataTable()


[ô] Carregar em DataTable existente
Dim table2 As New DataTable()
table2.Columns.Add([Ô]Preco[Ô], GetType(Integer))
table2.Columns.Add([Ô]Nome[Ô], GetType(String))
Dim query2 = From i In tabela_obj Where i.Preco > 9.99 Order By i.PrecoNew
query2.CopyToDataTable(table2, LoadOption.PreserveChanges)


A Classe usa Generic e importa Reflection (aconselho estudar essas técnicas que considero essenciais para um bom programador.

  
Imports System.Reflection

Public Class ObjectShredder(Of T)
Private _fi As FieldInfo()
Private _pi As PropertyInfo()
Private _ordinalMap As Dictionary(Of String, Integer)
Private _type As Type

Public Sub New()
_type = GetType(T)
_fi = _type.GetFields()
_pi = _type.GetProperties()
_ordinalMap = New Dictionary(Of String, Integer)()
End Sub

Public Function Shred(source As IEnumerable(Of T), table As DataTable, options As LoadOption?) As DataTable
If GetType(T).IsPrimitive Then
Return ShredPrimitive(source, table, options)
End If


If table Is Nothing Then
table = New DataTable(GetType(T).Name)
End If

table = ExtendTable(table, GetType(T))

table.BeginLoadData()
Using e As IEnumerator(Of T) = source.GetEnumerator()
While e.MoveNext()
If options IsNot Nothing Then
table.LoadDataRow(ShredObject(table, e.Current), options.Value)
Else
table.LoadDataRow(ShredObject(table, e.Current), True)
End If
End While
End Using
table.EndLoadData()
Return table
End Function

Public Function ShredPrimitive(source As IEnumerable(Of T), table As DataTable, options As LoadOption?) As DataTable
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

table.BeginLoadData()
Using e As IEnumerator(Of T) = source.GetEnumerator()
Dim values As [Object]() = New Object(table.Columns.Count - 1) {}
While e.MoveNext()
values(table.Columns([Ô]Value[Ô]).Ordinal) = e.Current

If options IsNot Nothing Then
table.LoadDataRow(values, options.Value)
Else
table.LoadDataRow(values, True)
End If
End While
End Using
table.EndLoadData()
Return table
End Function

Public Function ExtendTable(table As DataTable, type As Type) As DataTable
For Each f As FieldInfo In type.GetFields()
If Not _ordinalMap.ContainsKey(f.Name) Then
Dim dc As DataColumn = If(table.Columns.Contains(f.Name), table.Columns(f.Name), table.Columns.Add(f.Name, f.FieldType))
_ordinalMap.Add(f.Name, dc.Ordinal)
End If
Next
For Each p As PropertyInfo In type.GetProperties()
If Not _ordinalMap.ContainsKey(p.Name) Then
Dim dc As DataColumn = If(table.Columns.Contains(p.Name), table.Columns(p.Name), table.Columns.Add(p.Name, p.PropertyType))
_ordinalMap.Add(p.Name, dc.Ordinal)
End If
Next
Return table
End Function

Public Function ShredObject(table As DataTable, instance As T) As Object()

Dim fi As FieldInfo() = _fi
Dim pi As PropertyInfo() = _pi

If instance.[GetType]() IsNot GetType(T) Then
ExtendTable(table, instance.[GetType]())
fi = instance.[GetType]().GetFields()
pi = instance.[GetType]().GetProperties()
End If

Dim values As [Object]() = New Object(table.Columns.Count - 1) {}
For Each f As FieldInfo In fi
values(_ordinalMap(f.Name)) = f.GetValue(instance)
Next

For Each p As PropertyInfo In pi
values(_ordinalMap(p.Name)) = p.GetValue(instance, Nothing)
Next
Return values
End Function
End Class

Public Module DataSetLinqOperators

<System.Runtime.CompilerServices.Extension> _
Public Function CopyToDataTable(Of T)(source As IEnumerable(Of T)) As DataTable
Return New ObjectShredder(Of T)().Shred(source, Nothing, Nothing)
End Function

<System.Runtime.CompilerServices.Extension> _
Public Function CopyToDataTable(Of T)(source As IEnumerable(Of T), table As DataTable, options As System.Nullable(Of LoadOption)) As DataTable
Return New ObjectShredder(Of T)().Shred(source, table, options)
End Function

End Module
ANGELOATA 18/04/2013 10:55:31
#422123

Bom tentei com o copydatable no visual studio 2010, so que ocorre o seguinte erro:

[ô]copydatatable[ô] não é membro de system.link.iquerable

O que pode ser isso?

Att.

MJAC 24/04/2013 23:23:57
#422461
O erro ocorre por que copydatatable é para linq2object e não para linq2sql, você só pode usa métodos que podem ser convertidos para comandos SQL.
Tópico encerrado , respostas não são mais permitidas