这个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()是按原样编写的 - 最后两个参数仅在出现异常时使用...... ???
我很想彻底重构这段代码,因为它看起来很奇怪,但是因为我不太了解它,这可能是灾难的秘诀......
答案 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);
}
}