SqlDataAdapter vs SqlDataReader


130

Quais são as diferenças entre o uso de SqlDataAdapter e SqlDataReader para obter dados de um banco de dados?

Estou analisando especificamente seus prós e contras, bem como suas performances de velocidade e memória.

obrigado

Respostas:


193

SqlDataReader:

  • Mantém a conexão aberta até você terminar (não esqueça de fechá-la!).
  • Normalmente, só pode ser iterado uma vez
  • Não é tão útil para atualizar de volta para o banco de dados

Por outro lado, ele:

  • Possui apenas um registro na memória por vez, em vez de um conjunto de resultados inteiro (isso pode ser ENORME )
  • É o mais rápido possível para essa iteração
  • Permite iniciar o processamento dos resultados mais rapidamente (quando o primeiro registro estiver disponível). Para alguns tipos de consulta, isso também pode ser um grande problema.

SqlDataAdapter / DataSet

  • Permite fechar a conexão assim que terminar de carregar os dados, e pode até fechá-la automaticamente para você
  • Todos os resultados estão disponíveis na memória
  • Você pode iterá-lo quantas vezes precisar ou até mesmo procurar um registro específico por índice
  • Possui algumas faculdades internas para atualizar de volta para o banco de dados

À custa de:

  • Uso de memória muito maior
  • Você espera até que todos os dados sejam carregados antes de usá-los

Realmente depende do que você está fazendo, mas eu prefiro um DataReader até precisar de algo que seja suportado apenas por um conjunto de dados. SqlDataReader é perfeito para o caso comum de acesso a dados de ligação a uma grade somente leitura.

Para mais informações, consulte a documentação oficial da Microsoft .


5
O DataSet é um armazenamento de dados na memória, enquanto o datareader é apenas um meio para recuperar os dados. Em uma nota mais clara, você pode executar consultas Linq no DataSet, mas não em um datareader.
Partha Choudhury 4/11/2009

Na verdade, com um pouco de código extra, você certamente pode executar consultas linq (ou pelo menos uma consulta) em um datareader. Basta usar um bloco iterador para retornar o elenco do DataReader como um IDataRecord dentro do seu while (reader.Read())loop.
Joel Coehoorn

7
Esta resposta é enganosa. Se você agrupar os objetos SqlConnection e SqlDataReader com instruções "using" (como deveria, pois são IDisposable), a conexão será fechada automaticamente. E você pode usar um DataSet com um SqlDataReader: basta chamar DataSet.Load (SqlDataReader).
RickNZ

4
@RickNZ Não confie demais no uso de instruções para fechar as coisas para você. Eles chamam o método Dispose () do objeto, não o método Close (), e eu encontrei pelo menos um caso em que o Dispose realmente não fechou o objeto para mim. É sempre melhor incluir uma chamada explícita para o método close dentro do bloco using.
Cdaragorn 16/10/12

5
@Cdaragorn, os documentos do MSDN geralmente são bastante claros sobre Close () vs. Dispose (). No caso de SqlConnection, por exemplo, os documentos dizem que Close () e Dispose () são funcionalmente equivalentes. Eu não tenho nenhuma objeção a chamar Close (), mas as chamadas para Dispose () devem estar lá também para todos os IDisposables - e a maneira mais limpa de fazer isso é com uma instrução using. Nos casos em que você sabe que Dispose () não chama Close (), você deve chamar Close () dentro de um bloco final, se puder, não dentro do bloco de uso (para que ele ainda seja chamado se houver uma exceção).
21412 RickNZ # 2:

17

A resposta para isso pode ser bastante ampla.

Essencialmente, a principal diferença para mim, que geralmente influencia minhas decisões sobre a qual usar, é que, com um SQLDataReader, você está "transmitindo" dados do banco de dados. Com um SQLDataAdapter, você está extraindo os dados do banco de dados em um objeto que pode ser consultado ainda mais, além de executar operações CRUD.

Obviamente, com um fluxo de dados, o SQLDataReader é MUITO mais rápido, mas você pode processar apenas um registro por vez. Com um SQLDataAdapter, você tem uma coleção completa das linhas correspondentes à sua consulta no banco de dados para trabalhar com / passar seu código.

AVISO: Se você estiver usando um SQLDataReader, SEMPRE, SEMPRE, SEMPRE, certifique-se de escrever o código adequado para fechar a conexão, pois está mantendo a conexão aberta com o SQLDataReader. A falha em fazer isso ou o tratamento adequado de erros para fechar a conexão em caso de erro no processamento dos resultados CRIPPLE seu aplicativo com vazamentos de conexão.

Perdoe meu VB, mas esta é a quantidade mínima de código que você deve ter ao usar um SqlDataReader:

Using cn As New SqlConnection("..."), _
      cmd As New SqlCommand("...", cn)

    cn.Open()
    Using rdr As SqlDataReader = cmd.ExecuteReader()
        While rdr.Read()
            ''# ...
        End While
    End Using
End Using     

C # equivalente:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}

Se seu objetivo é obter dados usando uma consulta de seleção no db e acessar esses dados apenas em linhas diferentes, vá para a linha anterior, etc., você pode usar o SQLDatareader e carregá-lo em uma tabela de dados usando dtable.Load (rdr). Em seguida, navegue para cima e para baixo nesta tabela de dados. Você pode usar esse método em vez do DataAdapter ...
variável

14

Um SqlDataAdapter geralmente é usado para preencher um DataSet ou DataTable e, portanto, você terá acesso aos dados após o fechamento da conexão (acesso desconectado).

O SqlDataReader é um cursor conectado somente para encaminhamento e rápido, que tende a ser geralmente mais rápido do que preencher um DataSet / DataTable.

Além disso, com um SqlDataReader, você lida com seus dados um registro por vez e não armazena nenhum dado na memória. Obviamente, com um DataTable ou DataSet, você tem uma sobrecarga de alocação de memória.

Se você não precisar manter seus dados na memória, apenas para renderizar itens, vá para o SqlDataReader. Se você deseja lidar com seus dados de maneira desconectada, escolha o DataAdapter para preencher um DataSet ou DataTable.


10

Use um SqlDataAdapter ao desejar preencher um DataSet / DataTable na memória do banco de dados. Você tem a flexibilidade de fechar / descartar a conexão, passar a tabela / conjunto de dados na memória. Em seguida, você pode manipular os dados e persistir no banco de dados usando o adaptador de dados, em conjunto com InsertCommand / UpdateCommand.

Use um SqlDataReader ao desejar um acesso rápido aos dados de área de ocupação reduzida, sem a necessidade de flexibilidade, por exemplo, para passar os dados pela lógica de negócios. Isso é mais ideal para a recuperação rápida e com pouca memória de grandes volumes de dados, pois não carrega todos os dados na memória de uma só vez - com a abordagem SqlDataAdapter, o DataSet / DataTable seria preenchido com todos os dados. há muitas linhas e colunas, que exigirão muita memória para manter.


0

A função Fill usa um DataReader internamente. Se sua consideração for "Qual é mais eficiente?", O uso de um DataReader em um loop restrito que preenche uma coleção registro por registro provavelmente terá a mesma carga no sistema que o DataAdapter.Fill.

(System.Data.dll, System.Data.Common.DbDataAdapter, FillInternal.)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.