DataTable ou SqlDataReader
Boa tarde galera,
estou fazendo minha classe de acesso a dados e uma de conexao.
Na classe de conexao eu tenho um metodo que lista registros de uma determinada tabela.
Dúvida:
Qual a melhor forma de devolver os dados: SqlDataReader ou DataTable ?
Qual é o mais rápido para trabalhar ?
OBS: Não gostaria de usar o SqlDataReader em outra camada, pois não qro utilizar a System.Data.SqlClient, acho que não faz parte dessa camanda, e sim somente da classe do DB.
Falow.
estou fazendo minha classe de acesso a dados e uma de conexao.
Na classe de conexao eu tenho um metodo que lista registros de uma determinada tabela.
Dúvida:
Qual a melhor forma de devolver os dados: SqlDataReader ou DataTable ?
Qual é o mais rápido para trabalhar ?
OBS: Não gostaria de usar o SqlDataReader em outra camada, pois não qro utilizar a System.Data.SqlClient, acho que não faz parte dessa camanda, e sim somente da classe do DB.
Falow.
Tiago Melantonio
Curtidas 0
Respostas
Alexandre Lima.
15/04/2010
Tiago,
Existem duas formas de trabalhar com acesso à dados(no seu caso):
Conectado - SqlDataReader
Desconectado - DataSet e/ou DataTable usando TableAdapter para acesso ao banco
Tranbalhando de forma conectada à base de dados, é necessário uma conexão ativa com o banco de dados, isso pode gerar um pouco mais de processamento quando a massa de dados é relativamente grande.
Trabalhando de forma desconectada além de ser uma forma elegante de trabalhar com dados no .Net não é necessário uma conexão ativa durante a manipulação de dados.
Aconselho pesquisar sobre alguma ferramenta de ORM(Linq to Sql, Entity Framework, Nhibernate etc), isso irá facilitar muito o desenvolvimento de sua aplicação.
Existem duas formas de trabalhar com acesso à dados(no seu caso):
Conectado - SqlDataReader
Desconectado - DataSet e/ou DataTable usando TableAdapter para acesso ao banco
Tranbalhando de forma conectada à base de dados, é necessário uma conexão ativa com o banco de dados, isso pode gerar um pouco mais de processamento quando a massa de dados é relativamente grande.
Trabalhando de forma desconectada além de ser uma forma elegante de trabalhar com dados no .Net não é necessário uma conexão ativa durante a manipulação de dados.
Aconselho pesquisar sobre alguma ferramenta de ORM(Linq to Sql, Entity Framework, Nhibernate etc), isso irá facilitar muito o desenvolvimento de sua aplicação.
GOSTEI 0
Netasper
15/04/2010
Quem é que não gosta de fazer o menor esforço quando precisa codificar. Quanto se trata de acessar dados com VB .NET ou ASP .NET temos duas opções claras : DataSet e DataReader. E em se falando de pouco esforço quanto a codificação , com o DataSet podemos fazer o acesso basicamente com 3 linhas de código. Basta preencher o DataSet e a seguir fazer a interação usando um loop.
Mas e quanto ao desempenho ? Geralmente o desempenho é um requisito que vem em primeiro lugar , quer em aplicações Windows Forms quer em aplicações Web.
Quando se fala em desempenho a utilização de um DataReader leva vantagem sobre um DataSet. Com um DataReader você tem acesso aos dados assim que o objeto fica disponível e não necessita esperar , como no caso do DataSet , o seu preenchimento.
As vantagens do DataReader
A seguir temos um código que preenche um DataSet com o resultado de uma tabela e exibe o primeiro campo em cada linha:0
SqlConnection conn = new SqlConnection(connectionString);
SqlDataAdapter da = new SqlDataAdapter ("select * from tabela;",conn);
DataSet ds = new DataSet(); da.Fill(ds);
foreach (DataRow dr in ds.Tables[0].Rows)
{
Console.WriteLine(dr[0].ToString());
} Dim conn As New SqlConnection(connectionString)
Dim da As New SqlDataAdapter("select * from tabela;", conn)
Dim ds As New DataSet()
da.Fill(ds)
Dim dr As DataRow
For Each dr In ds.Tables(0).Rows
Console.WriteLine(dr(0).ToString())
Next dr C# VB.NET Observando o código você pode notar que a inspeção dos dados feita no loop foreach começa somente após o DataSet ter sido preenchido. Não dá para realizar outra tarefa enquanto o DataSet estiver sendo preenchido. Vamos ver agora o código que realiza a mesma tarefa usando um DataReader: SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("select * from tabela", con);
cmd.Connection.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while(dr.Read())
{
Console.WriteLine(dr.GetString(0));
}
dr.Close();
con.Close();
Dim con As New SqlConnection(connectionString)
Dim cmd As New SqlCommand("select * from tabela", con)
cmd.Connection.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While dr.Read()
Console.WriteLine(dr.GetString(0))
End While
dr.Close()
con.Close() C# VB .NET Neste caso a inspeção dos dados é feita tão logo os dados estiverem disponíveis através de um loop While , onde dr.Read() retorna false se não encontrar dados. O DataReader armazena um resultado por vez no cliente , e , com isto reduz o uso de memória e recursos do sistema. É óbvio que dependendo da situação somente um DataSet irá resolver a questão : serializar o resultado ou passar uma consulta para a próxima camada da sua aplicação , vai requerer uma coleção e um DataSet fornece um modelo adequado para estas tarefas. Na maioria das consultas empregadas nas aplicações Web , onde os dados é pesquisado , exibido e então descartado um DataReader irá aumentar o desempenho da sua aplicação de forma significativa. Então usar um DataReader é mais rápido que usar um DataSet . Certo ? Bem , sim e depende... Será que não existe um modo de otimizar o desempenho de um DataSet para justificar sua utilização ? Sim , existe e eu vou mostrar como você pode fazer isto. Antes vou mostrar o porque você quereria usar um DataSet. Os DataSet possuem um conjunto de funcionalidades que os DataReaders não possuem , dentre eles destacamos: Relacionamento Mestre-Detalhe com verificação de integridade Podemos efetuar operações com as colunas do lado do cliente (Soma, Média , etc..) que podem ser persistidas mesmo que os dados se alterem. Ordenação e Filtragem de dados no lado do cliente sem a necessidade de um round-trip ao Banco de dados Uma variedade de opções na vinculação de dados: DataGrid , WinForms e .NET Controls. Integração com o DataAdapter para atualização automática de atualizações. Poder ler e escrever diretamente uma representação XML de dados relacionados. Escolher usar um DataReader somente olhando a questão do desempenho irá fazer com que você não tenha acesso a estas funcionalidades. Existem outros aspectos negativos em um DataReader que talvez o façam mudar de idéia. Em sistemas multiusuários , enquanto os DataSets/DataAdapters liberam suas conexões e bloqueios assim que o preenchimento via método Fill termina , os DataReaders estão gerenciando a conexão e qualquer bloqueio aberto durante todo o tempo que durar o loop de inspeção de dados. (dr.Read()). Isto pode levar a uma maior contenção do seu banco de dados e com isto diminuir o desempenho . A única justificativa para usar um DataSet seria então melhorar seu desempenho. Melhorando o desempenho de um DataAdapter Você pode aproximar o desempenho de um DataAdapter de um DataReader desativando temporariamente algumas das funcionalidades avançadas padrão de um DataSet durante o processamento. Creio que os pontos chave em matéria de desempenho durante o processamento de um DataSet são a integridade referencial e a indexação que o DataSet usa para manter os dados internamente. Abaixo temos um código que mostra o preenchimento de um Dataset , via DataAdapter , que possui duas tabelas do banco de dados Northwind.mdb : Customers e Employees DataSet ds= new DataSet();
string strConn="Server=(local);dataBase=Northwind;user id=sa;password=;";
SqlConnection cn = new SqlConnection(strConn);
string strSQL="select * from Customers;select * from employees";
cn.Open();
SqlDataAdapter da = new SqlDataAdapter( strSQL,cn);
ds.Tables.Add("Customers");
ds.Tables.Add("Employees");
ds.EnforceConstraints =false;
ds.Tables["Customers"].BeginLoadData();
da.Fill(ds.Tables["Customers"]);
ds.Tables["Customers"].EndLoadData(); ds.Tables["Employees"].BeginLoadData();
da.Fill(ds.Tables["Employees"]);
ds.Tables["Employees"].EndLoadData();
dataGrid1.DataSource=ds.Tables["Customers"];
dataGrid2.DataSource=ds.Tables["Employees"];
cn.Close(); Neste código tomamos algumas medidas para melhorar o desempenho do DataSet. Vejamos quais: A primeira delas foi definir a propriedade - EnforceConstraints - como false ; isto desabilita a verificação das restrições durante a operação e pode tornar a operação mais rápida. Você pode voltar a definir o valor como True depois que os dados forem retornados dentro um loop try/Catch e tratando a exceção ConstraintException. Outro fator que onera o desempenho de um DataSet é o estabelecimento de uma chave primária. Podemos também desabilitar temporariamente a indexação e notificação interna. Para isto fazemos o seguinte: 1- Executamos o método BeginLoadData antes de usar o método Fill para desabilitar a notificação , indexação.
2- Executamos o método EndLoadData depois de usar o método Fill para habilitar a indexação a notificação. Estes métodos são membros da classe DataTable e por isso você vai precisar chamá-los para a DataTable particular que você esta preenchendo. Com isto melhoramos o desempenho do DataSet e com isto justificamos sua utilização afim de podermos usar seus recursos.
SqlDataAdapter da = new SqlDataAdapter ("select * from tabela;",conn);
DataSet ds = new DataSet(); da.Fill(ds);
foreach (DataRow dr in ds.Tables[0].Rows)
{
Console.WriteLine(dr[0].ToString());
} Dim conn As New SqlConnection(connectionString)
Dim da As New SqlDataAdapter("select * from tabela;", conn)
Dim ds As New DataSet()
da.Fill(ds)
Dim dr As DataRow
For Each dr In ds.Tables(0).Rows
Console.WriteLine(dr(0).ToString())
Next dr C# VB.NET Observando o código você pode notar que a inspeção dos dados feita no loop foreach começa somente após o DataSet ter sido preenchido. Não dá para realizar outra tarefa enquanto o DataSet estiver sendo preenchido. Vamos ver agora o código que realiza a mesma tarefa usando um DataReader: SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("select * from tabela", con);
cmd.Connection.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while(dr.Read())
{
Console.WriteLine(dr.GetString(0));
}
dr.Close();
con.Close();
Dim con As New SqlConnection(connectionString)
Dim cmd As New SqlCommand("select * from tabela", con)
cmd.Connection.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While dr.Read()
Console.WriteLine(dr.GetString(0))
End While
dr.Close()
con.Close() C# VB .NET Neste caso a inspeção dos dados é feita tão logo os dados estiverem disponíveis através de um loop While , onde dr.Read() retorna false se não encontrar dados. O DataReader armazena um resultado por vez no cliente , e , com isto reduz o uso de memória e recursos do sistema. É óbvio que dependendo da situação somente um DataSet irá resolver a questão : serializar o resultado ou passar uma consulta para a próxima camada da sua aplicação , vai requerer uma coleção e um DataSet fornece um modelo adequado para estas tarefas. Na maioria das consultas empregadas nas aplicações Web , onde os dados é pesquisado , exibido e então descartado um DataReader irá aumentar o desempenho da sua aplicação de forma significativa. Então usar um DataReader é mais rápido que usar um DataSet . Certo ? Bem , sim e depende... Será que não existe um modo de otimizar o desempenho de um DataSet para justificar sua utilização ? Sim , existe e eu vou mostrar como você pode fazer isto. Antes vou mostrar o porque você quereria usar um DataSet. Os DataSet possuem um conjunto de funcionalidades que os DataReaders não possuem , dentre eles destacamos: Relacionamento Mestre-Detalhe com verificação de integridade Podemos efetuar operações com as colunas do lado do cliente (Soma, Média , etc..) que podem ser persistidas mesmo que os dados se alterem. Ordenação e Filtragem de dados no lado do cliente sem a necessidade de um round-trip ao Banco de dados Uma variedade de opções na vinculação de dados: DataGrid , WinForms e .NET Controls. Integração com o DataAdapter para atualização automática de atualizações. Poder ler e escrever diretamente uma representação XML de dados relacionados. Escolher usar um DataReader somente olhando a questão do desempenho irá fazer com que você não tenha acesso a estas funcionalidades. Existem outros aspectos negativos em um DataReader que talvez o façam mudar de idéia. Em sistemas multiusuários , enquanto os DataSets/DataAdapters liberam suas conexões e bloqueios assim que o preenchimento via método Fill termina , os DataReaders estão gerenciando a conexão e qualquer bloqueio aberto durante todo o tempo que durar o loop de inspeção de dados. (dr.Read()). Isto pode levar a uma maior contenção do seu banco de dados e com isto diminuir o desempenho . A única justificativa para usar um DataSet seria então melhorar seu desempenho. Melhorando o desempenho de um DataAdapter Você pode aproximar o desempenho de um DataAdapter de um DataReader desativando temporariamente algumas das funcionalidades avançadas padrão de um DataSet durante o processamento. Creio que os pontos chave em matéria de desempenho durante o processamento de um DataSet são a integridade referencial e a indexação que o DataSet usa para manter os dados internamente. Abaixo temos um código que mostra o preenchimento de um Dataset , via DataAdapter , que possui duas tabelas do banco de dados Northwind.mdb : Customers e Employees DataSet ds= new DataSet();
string strConn="Server=(local);dataBase=Northwind;user id=sa;password=;";
SqlConnection cn = new SqlConnection(strConn);
string strSQL="select * from Customers;select * from employees";
cn.Open();
SqlDataAdapter da = new SqlDataAdapter( strSQL,cn);
ds.Tables.Add("Customers");
ds.Tables.Add("Employees");
ds.EnforceConstraints =false;
ds.Tables["Customers"].BeginLoadData();
da.Fill(ds.Tables["Customers"]);
ds.Tables["Customers"].EndLoadData(); ds.Tables["Employees"].BeginLoadData();
da.Fill(ds.Tables["Employees"]);
ds.Tables["Employees"].EndLoadData();
dataGrid1.DataSource=ds.Tables["Customers"];
dataGrid2.DataSource=ds.Tables["Employees"];
cn.Close(); Neste código tomamos algumas medidas para melhorar o desempenho do DataSet. Vejamos quais: A primeira delas foi definir a propriedade - EnforceConstraints - como false ; isto desabilita a verificação das restrições durante a operação e pode tornar a operação mais rápida. Você pode voltar a definir o valor como True depois que os dados forem retornados dentro um loop try/Catch e tratando a exceção ConstraintException. Outro fator que onera o desempenho de um DataSet é o estabelecimento de uma chave primária. Podemos também desabilitar temporariamente a indexação e notificação interna. Para isto fazemos o seguinte: 1- Executamos o método BeginLoadData antes de usar o método Fill para desabilitar a notificação , indexação.
2- Executamos o método EndLoadData depois de usar o método Fill para habilitar a indexação a notificação. Estes métodos são membros da classe DataTable e por isso você vai precisar chamá-los para a DataTable particular que você esta preenchendo. Com isto melhoramos o desempenho do DataSet e com isto justificamos sua utilização afim de podermos usar seus recursos.
GOSTEI 0
Danilo Mendes
15/04/2010
Amigo, já que você fala em camadas e classes, pq não avançar para uma outra coisa mais madura tipo o nHibernate ou até mesmo o EntityFramework?
Hoje pouca gente gente usa isso (dataset ou datareader) em sistemas novos por trazerem vários problemas na hora da manutenção.
Hoje pouca gente gente usa isso (dataset ou datareader) em sistemas novos por trazerem vários problemas na hora da manutenção.
GOSTEI 0
Tiago Melantonio
15/04/2010
Mas muitos lugares ainda usam o FrameWork 2.0, gostaria de usar procedures e não trabalhar como o linq, pois qualquer alteração precisa gerar uma nova dll.
Já trabalhei com o LINQ e não gostei muito da performace dele, acho q não tem nada igual ao SqlClient.
Já trabalhei com o LINQ e não gostei muito da performace dele, acho q não tem nada igual ao SqlClient.
GOSTEI 0
Netasper
15/04/2010
Amigo Danilo, vc esta inteiramente equivocado. Falar em maturidade com Linq e nHibernate é brincadeira ne?!?!
Procure ler um pouco mais sobre grandes empresas e sistemas robustos e veja qual usa Linq ou mesmo nHibernate. Nenhuma....
Geralmente, quando a empresa tem condições, eles desenvolvem seu proprio framework.
Mas na maioria das vezes é usado Enterprise Library. DAAB.
[]s
GOSTEI 0