我遇到了一个奇怪的问题,似乎找不到…的答案
我有一段代码,它使用事务和参数将数据插入到SQlite DB中。它从传递的对象List<T>
的列表中获取值。总共有74个参数。。。我的代码看起来像这个
dbConnection.Open();
using (SqliteTransaction transaction = dbConnection.BeginTransaction())
{
foreach (CardScryfall _card in _cards)
{
SqliteCommand com = dbConnection.CreateCommand();
com.CommandText = sql;
com.Parameters.Add("@dbid", SqliteType.Integer); //Mandatory
//Assign values to Parameters
com.Parameters[0].Value = GetNextDBID();
//Assign card properties to parameters
com.Parameters.Add("@objectName", SqliteType.Text);
com.Parameters[com.Parameters.IndexOf("@objectName")].Value = _card.objectName;
//Next 72 parameters are created the same way.
//Replace NULL with DBNull.Value
foreach (SqliteParameter par in com.Parameters)
{
if (par.Value == null)
{
par.Value = DBNull.Value;
}
}
//Execute query
com.Prepare();
com.ExecuteNonQuery();
transaction.Commit();
com.Dispose();
}
}
dbConnection.Close();
现在。。。当我删除using transaction
部分时,代码运行良好,只是速度非常慢。。。所以我添加了想把它封装到一个事务中,这样可以提高性能。
现在的问题是在添加参数的过程中(每次我遍历代码时都不同(,dbconnection.State
从打开变为关闭,所以当代码到达com.Prepare()
进行第一次插入时,我得到连接关闭的错误。。。我有10k多条记录要插入
我试着设置dbConnection.DefaultTimeout = 0
,但没有帮助。。。
你能帮忙吗???
感谢
更新:
我发现我的问题。。。函数GetNextDBID()
正在检索打开和关闭数据库连接的最后一个记录ID。。。所以我改变了代码,现在它工作得很好
无需在循环中创建命令。您应该创建一次,然后只为参数分配新值。
类似地,您不需要在循环的每次迭代中提交事务。最后做一次。
using (var dbConnection = new SqliteConnection(_connectionString))
{
dbConnection.Open();
using (SqliteTransaction transaction = dbConnection.BeginTransaction())
using (SqliteCommand com = dbConnection.CreateCommand())
{
com.CommandText = sql;
com.Parameters.Add("@dbid", SqliteType.Integer);
com.Parameters.Add("@objectName", SqliteType.Text);
// ...
com.Prepare();
foreach (CardScryfall _card in _cards)
{
com.Parameters["@dbid"].Value = GetNextDBID();
com.Parameters["@objectName"].Value = (object)_card.objectName ?? DBNull.Value;
// ...
_ = com.ExecuteNonQuery();
}
transaction.Commit();
}
}