在我的 WindowsCE / Compact Framework (.NET1.1) 项目中,我需要在代码中创建一个新表。我以为我可以这样做:
if (! TableExists("table42"))
{
CreateTable42();
}
public static bool TableExists(string tableName)
{
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(@"Data Source=\my documents\Platypus.SDF"))
{
sqlConn.Open();
string qryStr = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ?";
SqlCeCommand cmd = new SqlCeCommand(qryStr, sqlConn);
cmd.Parameters[0].Value = tableName;
cmd.CommandType = CommandType.Text;
int retCount = (int)cmd.ExecuteScalar();
return retCount > 0;
}
}
catch (Exception ex)
{
MessageBox.Show("TableExists ex.Message == " + ex.Message);
MessageBox.Show("TableExists ex.ToString() == " + ex.ToString());
MessageBox.Show("TableExists ex.GetBaseException() == " + ex.GetBaseException());
return false;
}
}
...但是对 TableExists() 的调用失败;并向我展示:
TableExists ex.Message ==
TableExists ex.ToString() == System.Data.SqlServerCe.SqlCeException at System.Data.SqlServerCe.SqlConnection.ProcessResults(Int32 hr) at ...at Open(boolean silent) ...
TableExists ex.GetBaseException() == [same as ex.ToString() above]
“Int32 小时” ... ??? Hec Ramsey 是什么?
正如之前在这些环境中记录的那样,我无法逐步完成这个项目,因此我依赖于对 MessageBox.Show() 的调用。
其余相关代码(如果可能感兴趣)是:
public static void CreateTable42()
{
try
{
using (SqlCeConnection con = new SqlCeConnection(@"Data Source=\my documents\Platypus.SDF"))
{
con.Open();
using (SqlCeCommand com = new SqlCeCommand(
"create table table42 (setting_id INT IDENTITY NOT NULL PRIMARY KEY, setting_name varchar(40) not null, setting_value(63) varchar not null)", con))
{
com.ExecuteNonQuery();
WriteSettingsVal("table42settingname","table42settingval");
}
}
}
catch (Exception ex)
{
MessageBox.Show("CreateTable42 " + ex.Message);
}
}
public static void WriteSettingsVal(string settingName, string settingVal)
{
using (SqlCeConnection sqlConn = new SqlCeConnection(@"Data Source=\my documents\Platypus.SDF"))
{
sqlConn.Open();
string dmlStr = "insert into tabld42 (setting_name, setting_value) values(?, ?)";
SqlCeCommand cmd = new SqlCeCommand(dmlStr, sqlConn);
cmd.CommandType = CommandType.Text;
cmd.Parameters[0].Value = settingName;
cmd.Parameters[1].Value = settingVal;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("WriteSettingsVal " + ex.Message);
}
}
}
更新
回答布拉德雷姆的评论:
我认为没有必要将参数括在引号中,因为其他工作代码如下:
cmd.Parameters.Add("@account_id", Dept.AccountID);
-和:
cmd.Parameters[0].Value = Dept.AccountID;
(它第一次在循环中以一种方式执行,然后以另一种方式执行(不要问我为什么)。
无论如何,只是为了笑,我确实从这里更改了 TableExists() 参数代码:
cmd.Parameters[0].Value = tableName;
...对此:
cmd.Parameters.Add("@TABLE_NAME", tableName);
...但我仍然得到完全相同的结果。
更新 2
在这里(http://msdn.microsoft.com/en-us/library/aa237891(v=SQL.80).aspx)我发现了这个:“当你打开 SQL Server 时,你必须指定 SQL Server CE 提供程序字符串CE 数据库。”
他们举了这个例子:
cn.ConnectionString = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0; data source=\Northwind.sdf"
我不这样做;我的 conn str 是:
using (SqlCeConnection sqlConn = new SqlCeConnection(@"Data Source=\my documents\CCRDB.SDF"))
这可能是我的问题吗?
更新 3
我接受了这位绅士的建议(http://www.codeproject.com/Answers/629613/Why-is-my-SQLServer-CE-code-failing?cmt=487657#answer1)并为 SqlCeExcpetions 添加了一个捕获,以便它是现在:
public static bool TableExists(string tableName)
{
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(@"Data Source=\my documents\CCRDB.SDF"))
{
sqlConn.Open();
string qryStr = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TABLE_NAME";
SqlCeCommand cmd = new SqlCeCommand(qryStr, sqlConn);
cmd.Parameters.Add("@TABLE_NAME", tableName);
cmd.CommandType = CommandType.Text;
int retCount = (int)cmd.ExecuteScalar();
return retCount > 0;
}
}
catch (SqlCeException sqlceex)
{
MessageBox.Show("TableExists sqlceex.Message == " + sqlceex.Message);
MessageBox.Show("TableExists sqlceex.ToString() == " + sqlceex.ToString());
return false;
. . .
SqlCeException 消息是:“存在文件共享冲突。不同的进程可能正在使用文件 [,,,,,]”然后“...processresults ... open ... getinstance ...”
更新 4
尝试使用 ctacke 的示例代码,但是:Transaction 绝对必要吗?对于我的场景/环境,我不得不将代码更改为以下代码,并且不知道事务应该是什么或如何构建它:
public static bool TableExists(string tableName)
{
string sql = string.Format("SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", tableName);
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(@"Data Source=\my documents\HHSDB.SDF"))
{
SqlCeCommand command = new SqlCeCommand(sql, sqlConn);
//command.Transaction = CurrentTransaction as SqlCeTransaction;
command.Connection = sqlConn;
command.CommandText = sql;
int count = Convert.ToInt32(command.ExecuteScalar());
return (count > 0);
}
}
catch (SqlCeException sqlceex)
{
MessageBox.Show("TableExists sqlceex.Message == " + sqlceex.Message);
return false;
}
}
更新 5
使用此代码,我得到的错误消息是,“错误消息可用于此异常,但无法显示,因为这些消息是可选的,当前未安装在此设备上。请安装 ... NETCFv35.Messages.EN.cab "
更新 6
太典型了,这个遗留的、古老的技术项目让我头疼。好像一次只允许打开一个连接,app一开始就打开一个;所以,我必须使用那个连接。但是,它是一个 DBConnection,而不是一个 SqlCeConnection,所以我不能使用这个代码:
using (SqlCeCommand com = new SqlCeCommand(
"create table hhs_settings (setting_id int identity (1,1) Primary key, setting_name varchar(40) not null, setting_value(63) varchar not null)", frmCentral.dbconn))
{
com.ExecuteNonQuery();
WriteSettingsVal("beltprinter", "ZebraQL220");
}
...因为作为 arg 传递给 SqlCeCommand 构造函数的已打开连接类型是 DBCommand,而不是预期/必需的 SqlCeConneection。
这段代码的触角太宽太根深蒂固,无法从根部撕下并进行重构以使其更明智:山脚下的一个试探性步骤会导致珠穆朗玛峰上的猛烈雪崩。