新しいASP.NETMVC 4アプリケーションを作成しましたが、最初にコードを使用したいと思います。ただし、データベースファイルがまだ存在しない場合、最初はデータベースファイルを作成していないようです。 App_Dataフォルダーから.mdfファイルを削除すると、アプリがデータベースにアクセスしようとしたときに次の例外が発生します。
System.Data.SqlClient.SqlException: Cannot attach the file '<path-to-db-file>.mdf' as database '<my-db-file-name>'.
デバッガーのアプリで実行すると、LazyInitializer.EnsureInitializedを呼び出すときに、InitializeSimpleMembershipAttribute :: OnActionExecutingメソッドで例外が発生していることがわかります。キャッチされた例外は次のとおりです。
[System.Reflection.TargetInvocationException] {"Exception has been thrown by the target of an invocation."} System.Reflection.TargetInvocationException
以下の内部例外を除いて:
[System.InvalidOperationException] {"The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.Microsoft.com/fwlink/?LinkId=256588"} System.InvalidOperationException
次に、その内部例外として上記の最初の例外があります。
私が間違っていることについて何か考えはありますか?
更新
まったく新しいMVC4アプリで試してみました。次のようにして複製できます。
同じ問題に遭遇し、私の解決策を見つけました ここ 。あなたがしなければならないのは、VS開発者コマンドプロンプトを開いてLocalDbを停止し、(引用符なしで)入力することだけです。
「sqllocaldb.exestopv11.0」
「sqllocaldb.exedeletev11.0」
次回EFは、ファイルとデータベースを再生成します。
アプリケーションのInitializeSimpleMembershipAttributeクラスを掘り下げると、それが継承するActionFilterAttributeクラスの次のオーバーライドされたメソッドが表示されます。
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
そのコメントに注意してください。アプリケーションは、実行ごとに1回チェックして、シンプルメンバーシップが適切に初期化されていることを確認します。クラスの上部にあるプライベート変数を見てください。
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
それらはすべて静的であり、すべて参照として渡されます。ここであなたの状況にとって重要なのは_isInitialized
です。 LazyInitializer.EnsureInitializedが行うことは、_isInitialized
フラグをチェックし、それがfalseの場合、渡されたrefターゲット、この場合はタイプSimpleMembershipInitializer
の_initializer
を初期化します。その時点で、フラグをtrueに設定し、次に進みます。 LazyInitializer.EnsureInitialized
がフラグが真であることを確認すると、ターゲットを返すだけです。そのフラグは静的変数であるため、アプリケーションの存続期間中その値を保持します。つまり、最初の初期化の後、EnsureInitializedは、データベースファイルが存在しなくなった場合でも、常にターゲットを返すだけです。つまり、初期化後に.mdfファイルを削除すると、アプリケーションは認識せず、アプリがデータベースからの読み取りまたは書き込みを試行したときに例外がスローされます。これを解決するには、アプリケーションを再起動する必要があります。つまり、使用している場合は開発サーバーを強制終了するか、IISでアプリケーションを再起動します。
これがあなたが直面している問題ですが、この質問に出くわした多くの人々は、ログインしようとしたときにこれと同様のエラーメッセージを受け取るという同様の異なる問題を抱えていると思います。
物理ファイル 'C:\ path\to\your\project\App_Data\dbfile.mdf'を開こうとしたとき、または作成しようとしたときに、CREATE FILEでオペレーティングシステムエラー5(アクセスが拒否されました)が発生しました。 CREATEDATABASEが失敗しました。リストされている一部のファイル名を作成できませんでした。関連するエラーを確認してください。
これは非常に簡単に解決できます。ここでも簡単に説明します。
デフォルトでは、Visual Studio 2012は、LocalDBと呼ばれるSQL ServerExpressの簡素化されたバージョンを使用します。 LocalDBは、アプリケーションの子プロセスを起動します。VisualStudioの開発サーバーでアプリケーションを実行している場合(たとえば、http:// localhost:[port]はブラウザーに表示されます)、両方のアプリケーションを実行しています。およびLocalDBは、SYSTEMまたはNETWORKSERVICEではなく、ユーザーアカウントの下にあります。これを修正するために必要なのは、プロジェクトのApp_Dataフォルダーの変更アクセス許可をユーザーに割り当てることだけです。ログインを再試行すると、.mdfファイルが正常に作成されます。
興味があれば、LocalDBについてもっと学ぶことができます ここ。
次のように、プロジェクトのルートフォルダーにあるGlobal.asaxファイルのApplication_Startメソッドでコードファーストデータベースの初期化を処理できます。
protected void Application_Start()
{
Database.SetInitializer<MyDBContext>(null);
}
SetInitializerにnullを渡しても、データベーステーブルは作成または変更されないため、手動で行う必要があります。
データベースが再生成されない理由は、Application_Startがアプリケーションの存続期間中に1回だけ起動されるためです。
MVCで生成されたコードは、「DefaultConnection」という名前のデータベース接続文字列で機能します。 Web.configで別の名前を使用した場合は、次の場所でこの名前を参照する必要があります。
(または、プロジェクトで「DefaultConnection」を検索してください)。
自動作成された.mdfファイルは、SQL管理ツールまたはオブジェクトエクスプローラーでのみ、エクスプローラーで削除しないでください。
あなたが得ている(そしてあなたが提供したステップで複製できる)問題は、データベースがまだLocalDbに登録されているということです。
IISExpressインスタンスを停止し、再起動する必要があります(Visual StudioでF5キーを押します)。その後、データベースを再度作成できるようになります。
このエラーが発生したときに修正されたのは、VSプロジェクトのApp.configファイルの接続文字列を変更したことです。
これを接続文字列に追加しました:
<connectionStrings>
<add name="Blog" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\kostadin\Database1.mdf" providerName="System.Data.SqlClient" />
これが他の誰かに役立つことを願っています。