2014年9月2日火曜日

[C#][SQL Server Express LocalDB] キー 'attachdbfilename' には無効な値です。

SQL Server Express CE(Compact Edition)が廃止されて、代わりにSQL Server LocalDB という SQL Server の機能がフルで使えるデータベースが使えるようになりました。前者はインプロセスでしたし、SQL Serverはサービスとして動作しますが、LocalDBは使用時にプロセスが起動し、使わなくなったらプロセスが終了します。これは便利だと思い、ちょうど以前 SQL Server CE を使用したアプリケーションのリメイクを行うこととなったので、ついでに LocalDB に移行しました。
順調に試験が終わってリリースしたところ、実機でエラーが出て起動できないと報告がありました。調べてみると次のエラーが出ていました。

キー 'attachdbfilename' には無効な値です。
   場所 System.Data.SqlClient.SqlConnectionString.VerifyLocalHostAndFixup(String& host, Boolean enforceLocalHost, Boolean fixup)
   場所 System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)
   場所 System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)
   場所 System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(String connectionString, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)
   場所 System.Data.SqlClient.SqlConnection.ConnectionString_Set(String value)
   場所 System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
   場所 System.Data.SqlClient.SqlConnection..ctor(String connectionString)

うぬぬ、よくわからんです。海外のサイトとかも含めて調べていたら、どうもバージョンが不一致だからダメだっていうことらしいです。実機には「Microsoft SQL Server 2014 Express のダウンロード 」をインストールしています。Visual Studio の 2013 で LocalDB を追加したら、LocalDB の は v11.0 で生成されますが、実機にインストールした LocalDB は v12.0 なんだとか。Visual Studio の最新のサービスパックを適用しても v11.0 で生成されてしまう。どうしろというのだ。まったく。

苦肉の策ですが、開発環境は v11.0 だけどインスタンス名を v12.0 にしてしまって接続することで回避できました。アプリケーション起動時に下記コマンドを実行します。


    // V12インスタンスのインストール
    var process = new Process()
    {
        StartInfo = new ProcessStartInfo(System.Environment.GetEnvironmentVariable("ComSpec"))
                    {
                        Arguments = "/c sqllocaldb create v12.0",
                        CreateNoWindow = true,
                        RedirectStandardOutput = true,
                        RedirectStandardInput = false,
                        UseShellExecute = false,
                    },
    };
    process.Start();
    var result = process.StandardOutput.ReadToEnd();
    process.WaitForExit();
    process.Close();
    if(!result.Contains("v12.0"))
    {
        throw new Exception(result);
    }

接続文字列(ConnectionString)を次のように変更します。

Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True
                       ↓
Data Source=(LocalDB)\v12.0;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True


これで開発機でも実機でもうまく動作するようになりました。




0 件のコメント:

コメントを投稿