4

私は、1つのウィンドウと、MVVM Lightからのメッセージを使用してrelayCommandsで互いに置き換えているいくつかのuserControlsで構成されるWPFのクックブックウィンドウアプリケーションに取り組んでいます。

アプリケーションは、entityFramework から生成された DB で動作します。ファイルの最初の実行以外の後に発生する問題は、プログラムが次のような多くの警告とエラーを表示することです。

Warning 1   Could not copy "...\cookbook\Cookbook.Services\Database1.mdf" to "bin\Debug\Database1.mdf". Beginning retry 1 in 1000ms. The process cannot access the file '...\cookbook\Cookbook.Services\Database1.mdf' because it is being used by another process. Cookbook.Services

ViewModelLocator には次のものがあります。

public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            SimpleIoc.Default.Register<MainWindowViewModel>();
            SimpleIoc.Default.Register<MainViewModel>();
            SimpleIoc.Default.Register<FoodTypeViewModel>();
            SimpleIoc.Default.Register<ShoppingCartViewModel>();
            SimpleIoc.Default.Register<MenuViewModel>();
            SimpleIoc.Default.Register<MenuListViewModel>();
            SimpleIoc.Default.Register<MenuCalendarViewModel>();
            SimpleIoc.Default.Register<ChooseFoodWindowViewModel>();
}

また、userControls を切り替えるために使用しているメッセージは、次のような ViewModels の新しいインスタンスを作成しています。

    BackToMainCommand = new RelayCommand(() =>
    {
        Messenger.Default.Send<ViewModelBase>(new MainViewModel());
    },
    () => true);

ViewModel をいじってシングルトンにし、システム内に単一のコピーしか存在しないようにしましたが、SimpleIoc には登録用のパブリック コンストラクターが必要です。また、それが私の問題に役立つかどうかもわかりません。また、言いませんでしたが、ViewModelLocator は xaml でのみ使用されるため、クリーンアップするためのインスタンスすらありません。(使い方が悪いのかもしれませんが、使い方がわかりません)

問題は、私が言及した多くの場所で作成され、それらのいくつかがおそらく *.mdf ファイルを保持しているため、すべての ViewModel をクリーンアップする方法と場所がわからないことです。

4

2 に答える 2

2

コメントで述べたように、あなたは

警告 1 「...\cookbook\Cookbook.Services\Database1.mdf」を「bin\Debug\Database1.mdf」にコピーできませんでした。1000ms に 1 回の再試行を開始します。

別のプロセスで使用されているため、プロセスはファイル '...\cookbook\Cookbook.Services\Database1.mdf' にアクセスできません。クックブック サービス

実行中/デバッグ中のアプリケーション用に作成されたプロセスが原因で、ビルドのコンパイラからの警告 (および十分な再試行エラーの後) メッセージ:

  1. まだ完了していない、または
  2. データベースファイルへのすべての接続を閉じていません。

そのため、再度ビルドすると、そのファイル ハンドルは開いたままであり、開いているファイルをコピーすることはできません。

質問に投稿したコードから、これの直接の原因を特定することは困難ですが、次の行:

Messenger.Default.Send<ViewModelBase>(new MainViewModel());

コンテナーからのシングルトン ライフサイクルインスタンスではなく、新しいインスタンスを返すため、明らかに問題があります。SimpleIoC適切な DI の観点からはまだ醜いですが、次のように変更できます。

Messenger.Default.Send<ViewModelBase>(ServiceLocator.Current.GetInstance<MainViewModel>());

したがって、 の新しいインスタンスは作成されませんMainViewModelが、IoC コンテナーからのインスタンスが返されます。

さらに、データベース コンテキストがコンテナーに登録され、それを必要とするビュー モデルに挿入されていることを確認したい場合があります。これを説明します (データベース コンテキスト/サービス クラスが呼び出されMyDbContext、 を実装IMyDbContextし、コンストラクター引数として接続文字列を受け取ると仮定します):

SimpleIoc.Default.Register<IMyDbContext>(() => new MyDbContext(GetMyConnectionString()));

ここで、アプリケーションの終了時に適切なクリーンアップが実行さDisposeれ、インスタンスで呼び出されるようIMyDbContextにする必要があります。また、破棄が必要なアプリケーション内のその他の潜在的なリソースも確認する必要があります。これがまだ行われていない場合は、MVVM Light を使用して、次のApplication.Exitイベントに反応することで行うことができますApplication

于 2015-04-18T09:29:00.133 に答える
0

あなたの問題は、おそらく DbContext の使用方法が原因です。あなたはあなたの質問にどのように対処するかを提示していませんでしたので、あなたの側で何が起こるかを推測しようとします. DbContext を使用した後は、すぐに破棄することを常に確認する必要があります。アプリケーションの存続時間全体にわたって保持する必要はありません。IoC に登録しているようには見えないので、ViewModel 内のどこかでインスタンス化するだけだと思います。このような場合、DbContext オブジェクトを常に using() 内に配置して、それらが確実に破棄されるようにする必要があります。通常の方法でアプリケーションを閉じるときに、データベースへの接続を開いてはいけません。

もう 1 つのケースは、VS でのアプリケーションのデバッグに関連しています。これはデフォルトで VS ホスティング プロセスで行われるため、[デバッグの停止] ボタンを押しても、接続が開かれている DbContext は破棄されず、VS ホスティング プロセスは強制終了されません。このような状況を回避するには、VS ホスティング プロセスを無効にすることをお勧めします。プロジェクト プロパティ -> デバッグ -> で設定し、[Visual Studio ホスティング プロセスを有効にする] のチェックを外すことができます。ただし、これにより、デバッグ時にアプリケーションが実行を開始する時間が少し短縮される場合があります。

于 2015-04-18T09:56:44.100 に答える