我应该重构这个,还是我的困惑导致谨慎?

时间:2013-04-01 18:22:57

标签: c# sql compact-framework sql-server-ce windows-ce

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

3)我无法解释为什么DBCommand()是按原样编写的 - 最后两个参数仅在出现异常时使用...... ???

我很想彻底重构这段代码,因为它看起来很奇怪,但是因为我不太了解它,这可能是灾难的秘诀......

2 个答案:

答案 0 :(得分:1)

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

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

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

我相信在哪种情况下?使用,@是可选的,但我不确定。如果它正在运作,我会说那是事实。

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

答案 1 :(得分: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方法写了一个重载来使用Legacy代码:

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