【问题标题】:SQLite insert looping error 'SQLiteException: 'database is locked'SQLite插入循环错误'SQLiteException:'数据库被锁定'
【发布时间】:2019-05-17 15:57:07
【问题描述】:

我正在尝试将 DataTable 插入到 SQLite 表中,并且我正在为此使用 foreach 循环,但它会抛出错误 SQLiteException: 'database is locked.

我试着用谷歌搜索这个,并尝试dispose我与using的联系

这是我的代码

public void Insert_to_db(DataTable data)
{
   foreach (DataRow row in data.Rows)
   {
           string alertTag = row["Alert Tag"].ToString();
           int group = Convert.ToInt32(row["Group"]);
           int line = Convert.ToInt32(row["Line"]);
           int task = Convert.ToInt32(row["Task"]);

           string sql = string.Format("insert into alert_tag (alert_tag, layer_group, line, task) values ('{0}','{1}','{2}','{3}')", alertTag, group, line, task);

           using (SQLiteConnection dbConn = new SQLiteConnection(Tools.SqliteConnString()))
           {
               using (SQLiteCommand command = new SQLiteCommand(sql, dbConn))
               {
                   dbConn.Open();
                   command.ExecuteNonQuery();
                   dbConn.Close();
               }
           }
   }
}

【问题讨论】:

  • 一般说明:使用占位符/参数化查询。 string.Format 应该“从不”用于 SQL 中的值。搜索“SQL 注入”。

标签: c# sqlite datatable dapper


【解决方案1】:

您需要更改代码,以便在using dbConn 内进行循环:

    using (SQLiteConnection dbConn = new SQLiteConnection(Tools.SqliteConnString()))
    {
        using (SQLiteCommand command = new SQLiteCommand(sql, dbConn))
        {
            dbConn.Open();

            string alertTag;
            int group;
            int line;
            int task;
            string sql;

            foreach (DataRow row in data.Rows)
            {
                alertTag = row["Alert Tag"].ToString();
                group = Convert.ToInt32(row["Group"]);
                line = Convert.ToInt32(row["Line"]);
                task = Convert.ToInt32(row["Task"]);
                sql = string.Format("insert into alert_tag (alert_tag, layer_group, line, task) values ('{0}','{1}','{2}','{3}')", alertTag, group, line, task);
                command.ExecuteNonQuery();
                dbConn.Close();                    
            }                
        }
    }
  1. 您可以考虑在保存之前对从 data.Rows 获得的值进行一些完整性检查。你现在对 sql 注入很开放。查看构建或使用parameters

  2. 我会研究像 Dapper 或 EF 这样的良好 ORM 以避免构建脆弱的插入语句

【讨论】:

  • 虽然效率不高,但问题中显示的循环方式应该没问题,没有其他并发访问/线程。 DB按顺序打开和关闭,无需外部访问,是“有效的”。环境中可能还有其他东西..
  • SQLiteCommand 中使用的sql var 是在之后声明的。
【解决方案2】:

所以正如@JhonB 建议的那样,我决定使用 dapper,但首先我必须 convert 我的 DataTabe 到对象列表

private List<AlertTagModel> convert(DataTable dt)
{
   var convertedData = (from rw in dt.AsEnumerable()
                        select new AlertTagModel() {
                            alert_tag = Convert.ToString(rw["AlertTag"]),
                            layer_group = Convert.ToInt32(rw["Group"]),
                            line = Convert.ToInt32(rw["Line"]),
                            task = Convert.ToInt32(rw["Task"])
                            }).ToList();
   return convertedData;
}

然后用 dapper 插入数据库

public void Insert_to_db(Object data)
{
     using (IDbConnection cnn = new SQLiteConnection(Tools.LoadConnectionString()))
     {
          cnn.Execute("insert into alert_tag (AlertTag, Layer_ID, Line_ID, Task_ID) values (@alert_tag, @layer_group, @line, @task)", data);
     }
}

解决了!

【讨论】:

    猜你喜欢
    • 2012-02-09
    • 2018-06-11
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多