我应该重构这个吗,还是我的困惑引起了谨慎?

本文关键字:我的 重构 我应该 | 更新日期: 2023-09-27 18:06:46

这段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()"' s (account_id)使用"@",而另一个(name)没有。哪种方式是正确的,或者"@"是可选的?

3)我无法理解为什么DBCommand()是这样写的-最后两个参数只在有异常的情况下使用…??

我想从根本上重构这段代码,因为它看起来很奇怪,但由于我真的不理解它,这可能是一个灾难的食谱…

我应该重构这个吗,还是我的困惑引起了谨慎?

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

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

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

我相信在这种情况下?时,@是可选的,但我不确定。如果它在工作,我想说就是这样。

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

?参数是旧的Access语法。

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

一般来说,SQL理解?参数,但最好只是改变,而你在那里,使它更容易理解。

我还在努力让头像&所有这些变量的尾部。如果我把它整理好,我将发布可编译的代码。

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

我像这样传递了你的数据集,添加了很多注释:

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);
  }
}