0

这个 SqlCe 代码对我来说看起来很奇怪:

cmd.CommandText = "INSERT INTO departments ( account_id, name) VALUES (?, ?)";
foreach(DataTable tab in dset.Tables)
{
    if (tab.TableName == "Departments")
    {
        foreach(DataRow row in tab.Rows)
        {
            Department Dept = new Department();
            if (!ret)
                ret = true;
            foreach(DataColumn column in tab.Columns)
            {

                if (column.ColumnName == "AccountID")
                {
                    Dept.AccountID = (string) row[column];
                }
                else if (column.ColumnName == "Name")
                {
                    if (!row.IsNull(column))
                        Dept.AccountName = (string) row[column];
                    else
                        Dept.AccountName = "";
                }
            }
            List.List.Add(Dept);
            . . .
            dSQL = "INSERT INTO departments ( account_id, name) VALUES ('" + Dept.AccountID + "','" + Dept.AccountName +"')";

            if (!First)
            {
                cmd.Parameters[0].Value = Dept.AccountID;
                cmd.Parameters[1].Value = Dept.AccountName;
            }

            if (First)
            {
                cmd.Parameters.Add("@account_id",Dept.AccountID);
                cmd.Parameters.Add("name",Dept.AccountName);
                cmd.Prepare();
                First = false;
            }

            if (frmCentral.CancelFetchInvDataInProgress)
            {
                ret = false;
                return ret;
            }

            try
            {
                dbconn.DBCommand( cmd, dSQL, true );
            } 
            . . .

    public void DBCommand(SqlCeCommand cmd, string dynSQL, bool Silent)
    {
        SqlCeTransaction trans = GetConnection().BeginTransaction();
        cmd.Transaction = trans;
        try
        {
            cmd.ExecuteNonQuery();
            trans.Commit();
        }
        catch (Exception ex)
        {
            try 
            {
                trans.Rollback();
            }
            catch (SqlCeException) 
            {
                // Handle possible exception here
            }
            MessageBox.Show("DBCommand Except 2"); // This one I haven't seen...
            WriteDBCommandException(dynSQL, ex, Silent);
        }
    }

我的问题是:

1)应该“?” 真的在分配给 cmd.CommandText 时使用,还是应该使用“@”来代替?

2)“cmd.Parameters.Add()”之一(account_id)使用“@”,另一个(名称)不使用。哪种方式是正确的,或者“@”是可选的?

3) 我不知道为什么 DBCommand() 是按原样编写的 - 最后两个 args 仅在出现异常时使用...???

我很想从根本上重构这段代码,因为它看起来很奇怪,但由于我并不真正理解它,这可能是灾难的根源......

4

2 回答 2

1

我相当肯定这篇文章会回答你的一些问题:

http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx

第二个图表解释了命名参数和位置 (?) 参数(在 OleDb 和 ODBC 中使用)之间的区别。

我相信在哪里?使用,@ 是可选的,但我不确定这一点。如果它有效,我会说情况就是这样。

DBCommand 中的内容似乎只是用于记录目的。如果执行失败,它会尝试回滚,然后使用 sql 命令 (in dynSQL) 记录异常。

于 2013-04-01T18:55:40.980 回答
0

?参数是较旧的 Access 语法。

我的猜测是这曾经是一个 Access 数据库,但有人在某个时候将它转换为 SQL CE。

通常,SQL 理解该?参数,但最好在您在那里时更改它,以便更容易理解。

我仍在尝试对所有这些变量做出正面和反面。如果我把它整理好,我会发布可编译的(sp?)代码。

编辑:我必须把它放到一个方法中并解决所有的 RED 错误,以确保我没有给你一些无法编译的东西。

我像这样将您的 DataSet 传递给它,并添加了很多评论:

private bool StrangeSqlCeCode(DataSet dset) {
  const string ACCOUNT_ID = "AccountID";
  const string DEPARTMENTS = "Departments";
  const string NAME = "Name";
  const string SQL_TEXT = "INSERT INTO departments (account_id, name) VALUES (@account_id, @name)";
  bool ret = false;
  //bool First = false; (we don't need this anymore, because we initialize the SqlCeCommand correctly up front)
  using (SqlCeCommand cmd = new SqlCeCommand(SQL_TEXT)) {
    // Be sure to set this to the data type of the database and size field
    cmd.Parameters.Add("@account_id", SqlDbType.NVarChar, 100);
    cmd.Parameters.Add("@name", SqlDbType.NVarChar, 100);
    if (-1 < dset.Tables.IndexOf(DEPARTMENTS)) {
      DataTable tab = dset.Tables[DEPARTMENTS];
      foreach (DataRow row in tab.Rows) {
        // Check this much earlier. No need in doing all the rest if a Cancel has been requested
        if (!frmCentral.CancelFetchInvDataInProgress) {
          Department Dept = new Department();
          if (!ret)
            ret = true;
          // Wow! Long way about getting the data below:
          //foreach (DataColumn column in tab.Columns) {
          //  if (column.ColumnName == "AccountID") {
          //    Dept.AccountID = (string)row[column];
          //  } else if (column.ColumnName == "Name") {
          //    Dept.AccountName = !row.IsNull(column) ? row[column].ToString() : String.Empty;
          //  }
          //}
          if (-1 < tab.Columns.IndexOf(ACCOUNT_ID)) {
            Dept.AccountID = row[ACCOUNT_ID].ToString();
          }
          if (-1 < tab.Columns.IndexOf(NAME)) {
            Dept.AccountName = row[NAME].ToString();
          }
          List.List.Add(Dept);
          // This statement below is logically the same as cmd.CommandText, so just don't use it
          //string dSQL = "INSERT INTO departments ( account_id, name) VALUES ('" + Dept.AccountID + "','" + Dept.AccountName + "')";
          cmd.Parameters["@account_id"].Value = Dept.AccountID;
          cmd.Parameters["@name"].Value = Dept.AccountName;
          cmd.Prepare(); // I really don't ever use this. Is it necessary? Perhaps.
          // This whole routine below is already in a Try/Catch, so this one isn't necessary
          //try {
          dbconn.DBCommand(cmd, true);
          //} catch {
          //}
        } else {
          ret = false;
          return ret;
        }
      }
    }
  }
  return ret;
}

我为您的 DBCommand 方法编写了一个重载以使用旧代码:

public void DBCommand(SqlCeCommand cmd, string dynSQL, bool Silent) {
  cmd.CommandText = dynSQL;
  DBCommand(cmd, Silent);
}

public void DBCommand(SqlCeCommand cmd, bool Silent) {
  string dynSQL = cmd.CommandText;
  SqlCeTransaction trans = GetConnection().BeginTransaction();
  cmd.Transaction = trans;
  try {
    cmd.ExecuteNonQuery();
    trans.Commit();
  } catch (Exception ex) {
    try {
      trans.Rollback(); // I was under the impression you never needed to call this.
      // If Commit is never called, the transaction is automatically rolled back.
    } catch (SqlCeException) {
      // Handle possible exception here
    }
    MessageBox.Show("DBCommand Except 2"); // This one I haven't seen...
    //WriteDBCommandException(dynSQL, ex, Silent);
  }
}
于 2013-04-01T18:50:44.583 回答