为什么这个 SQLite Insert 失败了?

Why is this SQLite Insert failing?

我有这段代码可以在 Windows CE / Compact Framework 应用程序的 SQLite 数据库中插入 1..N 条记录:

void IPlatypusDBUtils.SaveSiteMappingData(IEnumerable<SiteMapping> siteMappings)
{
    ExceptionLoggingService.Instance.WriteLog("Reached TestPlatypusDBUtils.SaveSiteMappingData");
    IEnumerable<SiteMapping> siteMaps = siteMappings;
    try
    {
        using (SQLiteConnection conn = new SQLiteConnection(PlatypusUtils.GetDBConnection()))
        {
            conn.Open();
            foreach (SiteMapping sm in siteMaps)
            {
                using (SQLiteCommand cmd = new SQLiteCommand(conn))
                {   
                    cmd.CommandText =
                            @"INSERT INTO SiteMapping (Id, SiteNumber, LocationNumber, SiteName) VALUES (@Id, @SiteNumber, @LocationNumber, @SiteName)";
                    cmd.Parameters.Add(new SQLiteParameter("LocationNumber", sm.Id));
                    cmd.Parameters.Add(new SQLiteParameter("SiteNumber", sm.SiteNumber.ToString())); // or Platypusconsts.currentsitenum ?
                    cmd.Parameters.Add(new SQLiteParameter("LocationNumber", sm.LocationNumber));
                    cmd.Parameters.Add(new SQLiteParameter("SiteName", sm.SiteName));
                    cmd.ExecuteNonQuery();
                } // using (SQLiteCommand cmd
            } // foreach (SiteMapping sm in siteMaps)
            conn.Close();
        } // using (SQLiteConnection conn
    } // try
    catch (Exception ex)
    {
        String msgInnerExAndStackTrace = String.Format(
            "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);               ExceptionLoggingService.Instance.WriteLog(String.Format("Exception in TestPlatypusDBUtils.SaveSiteMappingData: {0}", msgInnerExAndStackTrace));
    } // catch
}

...但无法插入任何记录。日志文件包含 "Reached TestPlatypusDBUtils.SaveSiteMappingData"(达到 Insert 方法)但不包含 "Exception in TestPlatypusDBUtils.SaveSiteMappingData"。 ExecuteNonQuery() 是否不是插入的正确调用,或者有什么问题?

更新

我在第一个日志写入的下方添加了这个:

MessageBox.Show(String.Format("siteMappings about to be inserted into SiteMapping table: {0}", siteMappings));

...我看到了这个:

我不知道这是否意味着 SiteMappings 中实际上没有任何内容,或者我试图以错误的方式查看内容。我首先附加了一个“.ToString()”,但它是灰色的,所以认为它没有实际意义并且会静音。

更新 2

显然根本问题是没有 SiteMappings 被传递给该方法。我添加了这个:

foreach (SiteMapping sm in siteMaps)
{
    MessageBox.Show(String.Format("this siteMap is {0}", sm));

...永远不会看到 "this siteMap is [bla]"。

为了将来参考,上面的尖叫声显示了 "empty" IEnumerable 中包含的内容。

更新 3

原来是数据问题(GIGO)。或者,试图进入的垃圾不会进入。

LocationNumber 提到了两次。

     ....
      //SHOULD BE [ID], PROBABBLY
      cmd.Parameters.Add(new SQLiteParameter("LocationNumber", sm.Id)); 


      cmd.Parameters.Add(new SQLiteParameter("SiteNumber", sm.SiteNumber.ToString()));                       
cmd.Parameters.Add(new SQLiteParameter("LocationNumber", sm.LocationNumber));
      cmd.Parameters.Add(new SQLiteParameter("SiteName", sm.SiteName));
       ....

我的猜测是在您决定站点映射是一种他们可以在 Windows CE 上存储信息而实际上不需要创建新文件的方式之前的人。

为什么 IEnumerable?传递一个列表怎么样?

那么,在您的服务器上,这些字段是什么样的?

我已经有 5 年多没有使用 SQLite 了,即便如此我也没有使用很长时间。

如果 SQLite 支持命名参数,你可以这样做(基于 Microsoft T-SQL):

private void IPlatypusDBUtils.SaveSiteMappingData(List<TSql> siteMappings) {
    var isnull = (siteMapping == null) ? "True" : "False";
    var count = (siteMapping == null) ? "-1" : siteMapping.Count.ToString();
    ExceptionLoggingService.Instance.WriteLog(
      String.Format("siteMapping is null? {0} siteMapping Count: {1}",
      isnull, count));
    string sqlCmd =
        @"INSERT INTO SiteMapping " +
        "(Id, SiteNumber, LocationNumber, SiteName) " +
        "VALUES " +
        "(@Id, @SiteNumber, @LocationNumber, @SiteName)";
    using (var cmd = new SQLiteCommand(sqlCmd, new SQLiteConnection(PlatypusUtils.GetDBConnection()))) {
        // Setup your parameters here,
        // using the data types found in your database,
        // before ever opening the database connection.
        cmd.Parameters.Add("@Id", DbType.Int);
        cmd.Parameters.Add("@SiteNumber", DbType.VarChar, 50); // or Platypusconsts.currentsitenum ?
        cmd.Parameters.Add("@LocationNumber", DbType.Int);
        cmd.Parameters.Add("@SiteName", DbType.VarChar, 50);
        try { // now open your connection
            cmd.Connection.Open();
            foreach (var sm in siteMappings) {
                cmd.Parameters["@Id"].Value = sm.Id;
                cmd.Parameters["@SiteNumber"].Value = sm.SiteNumber.ToString();
                cmd.Parameters["@LocationNumber"].Value = sm.LocationNumber;
                cmd.Parameters["@SiteName"].Value = sm.SiteName;
                cmd.ExecuteNonQuery();
            }
        } catch (SQLiteException ex) {
            // Focus your Exception on the SQLiteException
            String msgInnerExAndStackTrace = String.Format(
                    "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
            ExceptionLoggingService.Instance.WriteLog(String.Format("Exception in TestPlatypusDBUtils.SaveSiteMappingData: {0}", msgInnerExAndStackTrace));
        } finally {
            // Placing your Close command here will work even if
            // the code throws an exception.
            cmd.Connection.Close();
        }
    }
}

因为我没有在任何地方安装 SQLite,所以无法为您测试。

不过,如果可行,您只需要创建一个命令并只打开一个数据库连接。