Como armazenar massas de dados off-line e, em seguida, atualizá-lo em um banco de dados SQLite em lote?
-
19-09-2019 - |
Pergunta
Atualmente, estou tentando preencher um banco de dados SQLite com dezenas de milhares de dados de texto usando este este método:
SQLiteConnection = new SQLiteConnection(cntnStr);
connection.Open();
foreach(Page p in pages)
{
using (SQLiteCommand command = new SQLiteCommand(String.Format("Insert Into Pages (ID, Data, Name) Values ({0}, '{1}', '{2}')", id, p.Data, p.Name), connection))
command.ExecuteNonQuery();
}
No entanto, suspeito que fazer isso cerca de 10 vezes por segundo é provavelmente a abrandar o processo inteiro para baixo. Existe uma maneira que eu possa agrupar os dados na memória e depois adicionar cada 5000 registros ou menos no banco de dados em lote (por isso é mais rápido)?
EDIT: Super-importante: Certifique-se de realizar todos os seus comandos SQL dentro de um DbTransaction
- neste caso, um SQLiteTransaction
:
SQLiteTransaction trans = connection.BeginTransaction();
// SQL centric code - repeated inserts/changes
trans.Commit(); // adds your changes
Além disso, melhora o desempenho de 1000x.
Solução
Use uma consulta parametrizada, em vez de construir a consulta usando concatenação:
using (SQLiteConnection = new SQLiteConnection(cntnStr))
{
connection.Open();
string query = "Insert Into Pages (ID, Data, Name) Values (?, ?, ?)";
using (SQLiteCommand command = new SQLiteCommand(query, connection)
{
command.Parameters.Add("id", DbType.Int32);
command.Parameters.Add("data", DbType.String);
command.Parameters.Add("name", DbType.String);
foreach(Page p in pages)
{
command.Parameters["id"].Value = p.Id;
command.Parameters["data"].Value = p.Data;
command.Parameters["name"].Value = p.Name;
command.ExecuteNonQuery();
}
}
}
Este será mais rápido porque o DbCommand é criado apenas uma vez, e a consulta só é analisado uma vez. Além disso, você evitar os riscos de injeção SQL devido à concatenação
BTW, ter um olhar para este artigo por Robert Simpson (autor do provedor SQLite .NET)
Outras dicas
Você terá que lidar com escapando os dados a si mesmo, mas você pode usar uma inserção de lote.
IE:
Insert Into Pages (ID, Data, Name) Values (...),(...),(...),(...)
Você pode carregar a tabela do SQLite DB em um DataTable -Object, em seguida, insira seus registros para o DataTable a objetos e sincronizá-lo de volta a cada 5000 registros para o DB.