none
Preencher DataTable com DataReader (C#) RRS feed

  • Pergunta

  • Olá a todos.

          Estou tentando reproduzir o método usado pelo Laércio no webcast de criação de relatórios com o ReportViewer, mas ocorre um erro no momento em que tento preencher um DataTable com o conteúdo de um SqlDataReader.
    Logo a após a tentativa de preenchimento, o DataTable permanece vazio, e realizando um debug é possível verificar que o SqlDataReader fica com uma exceção InvalidOperationException que não aborta o funcionamento do programa.

          Como o código original era em VB, pode ser que eu tenha me enganado em algum trecho, ou talvez o método Load não funcione igual nas duas linguagens. Segue abaixo o código:

    1        public void listar() 
    2        { 
    3 
    4            string strConexao = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; 
    5            SqlConnection oConn = new SqlConnection(); 
    6            string strSQL; 
    7            DataTable oTable = new DataTable(); 
    8            SqlCommand oCmd; 
    9 
    10            try 
    11            { 
    12 
    13                rvPrintPreview.LocalReport.ReportPath = Server.MapPath("~/content/ReportViewer/ReporTeste.rdlc"); 
    14 
    15                oConn.ConnectionString = strConexao; 
    16                oConn.Open(); 
    17 
    18                strSQL = @"SELECT CLIE_NR_CLIENTE, CLIE_NM_RAZAO_SOCIAL, CLIE_NR_CNPJ, CLIE_NR_TELEFONE, CLIE_NR_FAX FROM WEB.CLIENTE"
    19 
    20                oCmd = new SqlCommand(strSQL, oConn); 
    21                oCmd.CommandText = strSQL; 
    22                oCmd.CommandType = CommandType.Text; 
    23 
    24                SqlDataReader oDataReader = oCmd.ExecuteReader(CommandBehavior.CloseConnection); 
    25                //Converter o DataReader para DataTable 
    26                oTable.Load(oDataReader); 
    27 
    28                ReportDataSource myReportDataSource = new ReportDataSource("ds_Cliente" , oTable); 
    29                rvPrintPreview.LocalReport.DataSources.Add(myReportDataSource); 
    30 
    31            } 
    32            catch(Exception err) 
    33            { 
    34                Page.Title = err.Message; 
    35            } 
    36 
    37        } 

           
          O trecho "oTable.Load(oDataReader);" não funciona e o DataTable permanece vazio. Assim o DataSource fica vazio e por consequência o relatório também.
    Na verdade o método Load() requer um objeto do tipo IDataReader, mas a mesma coisa acontecesse se um desses for colocado.

          Alguém sabe como posso fazer para preencher esse DataTable sem precisar criar uma estrutura para receber os dados do DataReader e inserir em DataRows antes de colocar no DataTable?

    Obrigado!

    sexta-feira, 20 de fevereiro de 2009 12:44

Respostas

Todas as Respostas

  • Só uma dúvida...


    O que essa linha                

    SqlDataReader oDataReader = oCmd.ExecuteReader(CommandBehavior.CloseConnection);

    especialmente "CommandBehavior.CloseConnection", faz?


    Por acaso ele executa a instrução e fecha a conexão...?


    Se for isso, o DataReader não pode ser lido com a conexão fechada (é modelo conectado e precisa de conexão constante para funcionar).

    Outra coisa, porque que você já não faz a consulta diretamente com um TableAdapter e DataTable?

    Ciência da Computação - Unincor - Graduado!!! - Nós programamos o mundo.
    sexta-feira, 20 de fevereiro de 2009 13:54
  •  Olá Gabriel.

    O método load() está correto.
    O problema talvez seja seu sql, vc já testou no SSMS para ver se está trazendo algum registro?
    Abraço,
    Marcelo Tamanini
    sexta-feira, 20 de fevereiro de 2009 14:01
  • Flávio,

    O trecho SqlDataReader oDataReader = oCmd.ExecuteReader(CommandBehavior.CloseConnection); executa a query e armazena no SqlDataReader.
    CommandBehavior.CloseConnection serve para fechar a conexão quando o reader for fechado.
    Testei também sem isso e mesmo assim continua não conseguindo preencher o DataTable.

    Por exemplo, se depois de preencher o DataReader mandar Response.Write(oDataReader[0].ToString()) os campos aparecem na tela normalmente, o problema está no preenchimento do DataTable mesmo.

    O motivo de não estar fazendo diretamente no TableAdapter é que um dos relatórios vai ter um filtro com um IN, e eu não consegui de jeito nenhum passar uma lista por parâmetro para o TableAdapter. Só consegui colocar um parâmetro por vez.

    Marcelo, a query está retornando os dados corretamente!

    sexta-feira, 20 de fevereiro de 2009 14:22
  • Gabriel,

       ReportDataSource myReportDataSource = new ReportDataSource("ds_Cliente" , oTable); 

    Esse parâmetro "ds_Cliente" está correto? O que ele representa, já que não o vejo no restante do seu código?


    Ps. Perdão pelas perguntas, mas é que eu nunca fiz as chamadas pra o ReportViewer, já que uso o Crystal Reports.

    Ciência da Computação - Unincor - Graduado!!! - Nós programamos o mundo.
    sexta-feira, 20 de fevereiro de 2009 15:30
  • Esse aí é o nome do objeto. Acontece que ele tem que ser igual ao nome dado ao datasource de origem na tela do relatório.




    sexta-feira, 20 de fevereiro de 2009 16:31
  • Olha, muito estranho... Se não estiver faltando nada nessa sintaxe para carregar o relatório, o load() está correto...

    Só para testar, você já experimentou executar um "read" no seu DataReader antes de fazer o load??


    Falou.

    Ciência da Computação - Unincor - Graduado!!! - Nós programamos o mundo.
    sexta-feira, 20 de fevereiro de 2009 18:29
  • Olha, dei uma procurada aqui, e achei um exemplo nesse link http://davidhayden.com/blog/dave/archive/2005/12/14/2623.aspx um pouco diferente do seu...

    private DataTable GetData() 
        DataTable dt = new DataTable(); 
     
        using (SqlConnection connection 
                 = new SqlConnection("ConnectionString")) 
        using (SqlCommand command = new SqlCommand()) 
        { 
            command.Connection = connection; 
            command.CommandText = "SELECT * FROM Customers"
     
            connection.Open(); 
            using (SqlDataReader reader = 
                command.ExecuteReader 
                    (CommandBehavior.CloseConnection)) 
            { 
                dt.Load(reader); 
            } 
        } 
     
        return dt; 

    Dá uma olhada aí e vê se consegue ajudar.

    Falou!

    Ciência da Computação - Unincor - Graduado!!! - Nós programamos o mundo.
    sexta-feira, 20 de fevereiro de 2009 18:55
  • Flávio, eu achei esse exemplo também, mas ele também não rodou!

    Contornamos a situação da seguinte maneira:

    Ao invés de jogar o resultado do SqlDataReader para um DataTable através do Load(), fizemos através de um novo DataSet sendo alimentado por um Adapter.

                    SqlDataAdapter adapter = new SqlDataAdapter(oCmd);
                    DataSet dsSource = new DataSet();
                    adapter.Fill(dsSource);

                    //Definindo o DataSource do relatório
                    ReportDataSource myReportDataSource = new ReportDataSource("ds_Cliente", dsSource.Tables[0]);
                    rvPrintPreview.LocalReport.DataSources.Add(myReportDataSource);

    Acho ainda que dá para remover esse DataSet e melhorar esse código. Vou fazer uns testes a mais depois.

    Obrigado!!
    sexta-feira, 20 de fevereiro de 2009 19:13
  • Você pode jogar do DataAdapter direto no DataTable...

    Daí não precisaria referenciar o DataTable no seu parâmetro   ReportDataSource myReportDataSource = new ReportDataSource("ds_Cliente", dsSource.Tables[0]);


    Bastaria fazer assim:
     
    SqlDataAdapter adapter = new SqlDataAdapter(oCmd); 
    DataTable dtSource = new DataTable(); 
    adapter.Fill(dtSource); 
     
    //Definindo o DataSource do relatório 
    ReportDataSource myReportDataSource = new ReportDataSource("ds_Cliente", dtSource); 
    rvPrintPreview.LocalReport.DataSources.Add(myReportDataSource); 


    Ciência da Computação - Unincor - Graduado!!! - Nós programamos o mundo.
    sexta-feira, 20 de fevereiro de 2009 19:20


  • Olá Pessoal,


    Segue alguns links para ajudar nessa implementação:


    Preencher DataTable com SQLDataReader em C#
    http://www.devmedia.com.br/articles/viewcomp.asp?comp=5885


    datareader to datatable.
    http://www.dotnetspider.com/forum/ViewForum.aspx?ForumId=11020


    DataTable and DataReader
    http://www.daniweb.com/forums/thread102459.html


    Convert the DataReader output to DataTable in C#
    http://rmanimaran.wordpress.com/2007/10/17/convert-the-datareader-output-to-datatable-in-c/


    Convert a DataReader to DataTable in ASP.NET
    http://www.dotnetcurry.com/ShowArticle.aspx?ID=143&AspxAutoDetectCookieSupport=1



    Espero que estes links ajudem mesmo.

    Abraços, bons estudos e desenvolvimento.


    Magno Machado Borba |- Se o post foi util ou resposta nao esqueca de marcar.
    sábado, 21 de fevereiro de 2009 17:36
  • Gabriel,

    Esse erro foi simples de resolver.

     Você não conseguiu apenas por um motivo:

    Você  esqueceu  de fazer a referência da  variavel de conexão no SqlConnection.

    Segue abaixo como você enviou:

    1         public void listar() 
    2         { 
    3  
    4             string strConexao = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; 
    5             SqlConnection oConn = new SqlConnection(); 
    6             string strSQL; 
    7             DataTable oTable = new DataTable(); 
    8             SqlCommand oCmd; 
    E agora, como deveria ser:
    1         public void listar() 
    2         { 
    3  
    4             string strConexao = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; 
    5             SqlConnection oConn = new SqlConnection("strConexao"); 
    6             string strSQL; 
    7             DataTable oTable = new DataTable(); 
    8             SqlCommand oCmd; 
    Abraço, Espero que tenha resolvido!
    • Sugerido como Resposta Tiago-vb.net sexta-feira, 19 de março de 2010 12:06
    sexta-feira, 19 de março de 2010 12:04
  • Tu nunca deverias usar datareader para preencher uma tabela. nao e uma boa forma de prgramar.

    Datareader foi ciado para fazer pesquiza rapidas  obter resultados rapidos nao para encher tabelas.

     

     


    Just Be Humble Malange!
    sexta-feira, 19 de março de 2010 15:21
    Moderador