Para a inserção e atualização de dados massivos, o ADO.NET não é tão bom quanto o JDBC tem um modelo unificado para operações em lote.
PreparedStatement ps = conn.prepareStatement("inserir ou atualizar arg1,args2....");
então você pode
for(int i=0;i<100000000000000;i++){
ps.setXXX(realArg);
.....
addBatch();
if(i%500==0){ //Suponha que quinhentos itens sejam enviados uma vez
ps.executeBatch();
//limpa lote de parâmetros
}
}
ps.executeBatch();
Tal operação não só traz um desempenho extremamente alto, mas também é muito conveniente. Normalmente, no ADO.NET, para implementar tal função, as APIs Addbat e CommitBat devem ser fornecidas diretamente na interface Command ou na interface DataAdapter, mas ADO. NET's Mas não é implementado de forma tão simples, mas exige que os desenvolvedores passem por soluções alternativas complexas.
Para um grande número de operações de inserção, você pode usar um DataTable vazio para adicionar as linhas a serem inseridas e, em seguida, limpar a tabela após um certo número de envios.
Não é muito complicado de implementar:
DateTime início = DateTime.Now;
string conexãoString = ...;
usando(SqlConnection conexão = new SqlConnection(connectionString))...{
conexão.Open();
SqlDataAdapter sd = new SqlDataAdapter();
sd.SelectCommand = new SqlCommand("selecione devid,data_time,data_value do CurrentTest", conn);
sd.InsertCommand = new SqlCommand("inserir em CurrentTest (devid,data_time,data_value)"
+ "valores(@devid,@data_time,@data_value);", conn);
sd.InsertCommand.Parameters.Add("@devid", SqlDbType.Char, 18, "devid");
sd.InsertCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.InsertCommand.Parameters.Add("@data_value", SqlDbType.Int, 8, "data_value");
sd.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
Conjunto de dados DataSet = new DataSet();
sd.Fill(conjunto de dados);
Aleatório r = novo Aleatório(1000);
for (int i = 0; i < 100000; i++) ...{
objeto[] linha = ...{"DEVID"+i,DateTime.Now.ToString("aaaa-MM-dd HH:mm:ss"),r.Next(1,1000) };
dataset.Tables[0].Rows.Add(linha);
se (eu% 300 == 0)...{
sd.Update(dataset.Tabelas[0]);
conjunto de dados.Tables[0].Clear();
}
}
sd.Update(dataset.Tabelas[0]);
conjunto de dados.Tables[0].Clear();
sd.Dispose();
conjunto de dados.Dispose();
conexão.Fechar();
}
TimeSpan ts = DateTime.Now - início;
MessageBox.Show("ts = " + ts.TotalMilliseconds);
Para este teste, levei 28 segundos para inserir 100.000 dados. O desempenho é bastante impressionante, mas para atualizações em lote e exemplos de pesquisa em todo o mundo, os registros são preenchidos no DataSet e então as linhas são extraídas.
Para atualizar, no que diz respeito ao meu teste com uma pequena quantidade de dados, preencher 100.000 dados no DataSet não funciona mais. Se forem milhões, como você o opera? em lote no DataSet Medium? Em outras palavras, quais registros eu desejo atualizar devem ser selecionados para consultar esses registros?
Então ainda utilizo um DataTable vazio para adicionar os registros a serem atualizados:
sd.SelectCommand = new SqlCommand("selecione devid,data_time,data_value de CurrentTest onde 1=0", conn);
//A condição 1=0 garante uma tabela vazia.
sd.UpdateCommand = new SqlCommand("atualizar conjunto CurrentTest data_time = @data_time,data_value = @data_value onde devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
for(int i=0;i<300;i++){
............................
dataset.Tables[0].Rows.Add(linha);
}
sd.Update(dataset.Tables[0]);
Tente atualizar 300 registros primeiro. Se for bem-sucedido, ele atualizará todos os registros em um loop, mas solicitará que a operação de inserção exija InsertCommand porque é uma tabela vazia e, em seguida, a operação Adicionar Linha. Neste momento, RowState é adicionado.
Se Update for enviado ao banco de dados neste momento, a operação de inserção será executada e não poderá ser atualizada.
for(int i=0;i<300;i++){
............................
linha = {preencher o valor inicializado};
dataset.Tables[0].Rows.Add(linha);
}
conjunto de dados.AcceptChanges();
for(int i=0;i<300;i++){
............................
conjunto de dados.Tables[0].Rows[i][x] = "xxxxxxx";
............................
}
sd.Update(dataset.Tables[0]);
Primeiro insira os dados no DataTable, depois use AcceptChanges() para modificar o RowState para UnChanged e, em seguida, modifique os dados na tabela para alterar o estado UnChanged.
Altere o DataTable do estado atual para Original e, em seguida, atualize a linha do DataTable, você pode usar
A atualização foi bem-sucedida, mas é realmente inconveniente fazer isso.
Ajuste a ideia, primeiro pegue 200 entradas do banco de dados (o tamanho da atualização em lote) e obtenha diretamente um DataTable Original.
sd.SelectCommand = new SqlCommand("selecione os 200 principais devid,data_time,data_value do CurrentTest", conn);
Conjunto de dados DataSet = new DataSet();
sd.Fill(conjunto de dados);
Utilize esses 200 espaços para colocar outros dados a serem atualizados e veja:
para (int i = 0; i < 100; i++)
{
conjunto de dados.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
dataset.Tables[0].Rows[i]["data_value"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+(i+10000);//Atualiza registros de DEVID10000 para DEVID10200
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
OK, sucesso, haha. Continue preenchendo os dados a serem atualizados neste espaço e envie-os quando estiver cheio. Dessa forma, são necessários apenas alguns ciclos para atualizar 100.000 dados.
DateTime início = DateTime.Now;
string conexãoString = "";
usando(SqlConnection conexão = new SqlConnection(connectionString))...{
conexão.Open();
SqlDataAdapter sd = new SqlDataAdapter();
sd.SelectCommand = new SqlCommand("selecione os 200 principais devid,data_time,data_value do CurrentTest", conn);
Conjunto de dados DataSet = new DataSet();
sd.Fill(conjunto de dados);
Aleatório r = novo Aleatório(1000);
sd.UpdateCommand = new SqlCommand("atualizar CurrentTest "
+ "set data_time = @data_time,data_value = @data_value onde devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
for (int contagem = 0; contagem <100000;)
...{
for (int i = 0; i < 200; i++,contagem++)
...{
conjunto de dados.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
dataset.Tables[0].Rows[i]["data_value"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+count;
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tabelas[0]);
}
conjunto de dados.Tables[0].Clear();
sd.Dispose();
conjunto de dados.Dispose
http://www.cnblogs.com/Seabiscuit/archive/2010/05/25/1743341.html