VB.NET - Preenchendo um DataTable com um DataReader
Para preencher um DataTable em um DataSet geralmente você usa um DataAdapter. certo ?
E se você precisar preencher um DataTable de um DataSet a partir de um DataReader ? Acha que é possível ?
Neste momento é que os conhecimentos básicos das propriedades e características OOP da linguagem VB.NET se fazem valer. Se você anda meio esquecido vou fazer uma reprise destes conceitos.
O ADO.NET é implementando em várias classes que podem ser divididas em dois grupos :
O xis da questão é que para preencher um DataTable usamos o método Fill do objeto DataAdapter e que o DataReader não possui o método Fill.
Mas se olharmos com mais atenção para a classe DbDataAdpater , classe a partir da qual todos os tipos xxxDataAdapter herdam, iremos perceber que ela expõe um método sobrecarregado e protegido para o método Fill. E , o melhor da estória, este método pode tomar um objeto IDataReader como argumento. Sua sintaxe é :
Overloads Protected Overridable Function Fill(DataSet, String, IDataReader, Integer, Integer) As Integer
Podemos então usar estes métodos . Certo ?
Sim , podemos usar estes métodos usando Reflection pois eles são protected.
Podemos então criar um método , função ou procedure para efetuar o preenchimento de um DataTable a partir de um DataReader. O código da rotina poderia ser o descrito abaixo:
Sub PreencheDataSetDeDataReader(ByVal ds As DataSet, ByVal table As String, ByVal dr As IDataReader) ' Cria um xxxDataAdapter do mesmo tipo de um DataReader Dim tipoDataReader As Type = CObj(dr).GetType Dim nomeTipo As String = tipoDataReader.FullName.Replace("DataReader", "DataAdapter") Dim tipoDataAdapter As Type = tipoDataReader.Assembly.GetType(nomeTipo) Dim da As Object = Activator.CreateInstance(tipoDataAdapter) ' invoca o método protegido Fill que toma um objeto IDataReader Dim args() As Object = {ds, table, dr, 0, 999999} tipoDataAdapter.InvokeMember("Fill", BindingFlags.InvokeMethod Or BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, da, args) ' fecha o DataReader dr.Close() End Sub |
Vamos então , usando a rotina acima mostrar como podemos preencher um DataGrid com os dados de um DataTable preenchido a partir de um DataReader.
Inicie um novo projeto no VS.NET do tipo Windows Application usando a linguagem VB.NET e no formulário padrão insira um componente DataGrid , um componente Button e outro Label.
Declare os seguintes imports no projeto:
Imports
System.data.sqlclientAgora no evento Click do botão de comando insira o código que irá usar a rotina PreencheDataSetDeDataReader().:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As New SqlConnection("server=(local);trusted_connection=true;database=Northwind;Integrated Security=SSPI") cn.Open() Dim cm As New SqlCommand("SELECT * FROM Employees", cn) Dim dr As SqlDataReader = cm.ExecuteReader Dim ds As New DataSet PreencheDataSetDeDataReader(ds, "Empregados", dr) DataGrid1.DataSource = ds.Tables("Empregados") End Sub |
Estou efetuando uma conexão com o banco de dados Northwind do SQL Server e preenchendo o DataTable com os dados da tabela Employees.
Observe que estou passando o DataSet - ds , a tabela Empregados , e o DataReader - dr , que foi obtido anteriormente. Executando o projeto teremos o resultado abaixo:
Sem ter as noções de orientação a objeto jamais chegaríamos a esta solução.
Eu sei é apenas VB , mas eu gosto...
José Carlos Macoratti