なか日記

一度きりの人生、楽しく生きよう。

接続文字列に"|DataDirectory|"を使用したMSTestプロジェクトでやっとくこと

何回も躓いてて、「ええ加減覚えてくれ、俺」という思いを込めて。

App.configなどでデータベースの接続文字列を記述する際、「|DataDirectory|」という代替文字列が使用できます。

  <connectionStrings>
    <add name="DataContext" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\B2Web.mdf;Initial Catalog=B2Web;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

これを使って、テストプロジェクト(MSTest)を実行するとデータベース作成のタイミングで以下の様な例外が発生します。

初期化メソッド B2Web.Tests.Models.Data.DataContextTest.SetUp は例外をスローしました。System.Data.SqlClient.SqlException: System.Data.SqlClient.SqlException: A file activation error occurred. The physical file name '\B2Web.mdf' may be incorrect. Diagnose and correct additional errors, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.。

'\B2Web.mdf'が不正ということですが、どうも|DataDirectory|が空文字("")になっているっぽい。 以下の情報を見る限り「アプリケーションが格納されているフォルダー」になるんじゃないの?と思ったのですが、テストプロジェクトでは挙動が異なるみたいです。

AppDomain.SetData を呼び出すことにより、AppDomain の DataDirectory プロパティを設定します。

DataDirectory プロパティを設定しない場合、データベース フォルダーのパスへのアクセスには既定で次の規則が適用されます。

  • アプリケーションをクライアント コンピューター上のディレクトリに配置する場合、データベースへのパスはアプリケーションが格納されているフォルダーになります。たとえば、MyApp.exe が /MyDir フォルダーにある場合、アクセス先は /MyDir フォルダーになります。

  • アプリケーションが ClickOnce で実行される場合、専用のデータ フォルダーが作成され、そのフォルダーがアクセス先となります。

  • Web アプリケーションの場合のアクセス先は App_Data フォルダーです。AppDomain.SetData を使用すると、App_Data フォルダーに DataDirectory を設定できます。

デスクトップ コンピューターへのインストールと配置 (SQL Server Compact)

いろいろ調べた結果、ナオキさんのブログに書かれてた方法で解決させてもらいました。

以下の様にDataDirectoryの値として、ビルド先([プロジェクト名]\bin\Debugや[プロジェクト名]\bin\release)を指定する為のクラスを追加しました。

[TestClass]
public static class DataDirectoryInitialize
{
    [AssemblyInitialize]
    public static void AssemblyInitialize(TestContext context)
    {
        AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory);
    }
}

個人的な好みでビルド先にしましたが、テスト結果として データベースも残しておきたい場合はナオキさんのブログに書かれていた「context.TestDeploymentDir」などを指定するといいと思います。

経験不足ですなぇ・・・