私の 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);
}
}
}
アップデート
Brad Rem のコメントへの回答:
他の作業コードは次のようになるため、param を引用符で囲む必要はないと思います。
cmd.Parameters.Add("@account_id", Dept.AccountID);
-と:
cmd.Parameters[0].Value = Dept.AccountID;
(ループ内で最初に 1 つの方法で実行し、その後は別の方法で実行します (理由は聞かないでください)。
とにかく、にやにや笑いのために、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 ) 私はこれを見つけました: "Caution You must specify the SQL Server CE provider string when you open a SQL Server CEデータベース。」
彼らはこの例を挙げています:
cn.ConnectionString = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0; data source=\Northwind.sdf"
私はそうしていません。私の接続文字列は次のとおりです。
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 メッセージは次のとおりです。
更新 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
あまりにも典型的なことですが、このレガシーで古代のテクノロジー プロジェクトは、私に頭痛の種を与えています。一度に開くことができる接続は 1 つだけのようで、アプリは最初から 1 つを開きます。だから、私はその接続を使用する必要があります。ただし、これは SqlCeConnection ではなく DBConnection であるため、次のコードは使用できません。
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");
}
...引数として SqlCeCommand コンストラクターに渡された既に開いている接続タイプは DBCommand であり、期待/必須の SqlCeConneection ではないためです。
このコードの触手は幅が広すぎて、根っこを引き裂いてより賢明なものにするためにリファクタリングすることはできません。ふもとの丘での一時的な一歩が、エベレストで猛烈な雪崩を引き起こします。