2

ちょっと最近、拡張メソッドの使い方を学び、現在のプロジェクトでそれを実装することに非常に興奮しています。静的クラスでdbcontextを使用するには? (ObjectDisposedException)

私の目標: 私はリンクが私のナビゲーションバーに表示するためにどのナビゲーションを決定することができるように複数のコントローラでそれを使用するつもりですので、私は、エントリはヘルパークラスで私のテーブルに存在するかどうかを確認したいです:enter image description here

私の問題: 私は私の静的ヘルパークラスで私のdbcontextにアクセスする方法を知りません。私のdbcontextコントローラは、静的クラスを渡す方法を知らない引数をとります。私は新しいdbcontextを作成すると、以下で説明したスコープの問題を解決できると思いますが、私はオプションの引数をコンストラクタに渡すことはできません。

enter image description here

現在では、Startup.csクラスで構成されています。引数としてApplicationDbContextを渡す :私が試した何 enter image description here

。これは私のコントローラの単一のメソッド呼び出しで機能しますが、複数の拡張メソッドを呼び出すとき(ユーザーが持つゲームアカウントを調べるために)、ObjectDisposedExceptionが発生します。

ObjectDisposedException:破棄されたオブジェクトにアクセスできません。このエラーの一般的な原因は、依存性注入から解決されたコンテキストを破棄し、後でアプリケーションの別の場所で同じコンテキストインスタンスを使用しようとすることです。これは、コンテキストでDispose()を呼び出す場合、またはusingステートメントでコンテキストをラップする場合に発生する可能性があります。依存性注入を使用している場合は、依存性注入コンテナがコンテキストインスタンスを処理するようにする必要があります。 オブジェクト名: 'ApplicationDbContext'。

私が理解しているところでは、最初のメソッド呼び出しが完了したときにコンテキストを破棄し、次の呼び出しで同じコンテキストを使用しようとしているスコープの問題です。その問題を回避するために私は何ができますか?

私はこのリンクCannot access a disposed object in ASP.NET Core when injecting DbContextを読んでみましたが、それはStartup.csクラスにあるApplicationBuilderを必要とするため、私には役に立たなかった。

enter image description here

ソリューションのアップデート 私は変数にそれを置くので、私はすべてのメソッド呼び出しの後dbcontextに配置されました。拡張子があなたを意味するものではありません、あなたに新しい、光沢があるものの、

enter image description here

おかげでデビッドとサイモンは

+1

をあなたは* '* HasDota2Account()'を呼び出す方法は?あなたは 'DbContext'をそれに渡していますか? '_context'はどこから来たのですか?このエラーは、実際には 'UpdateNavLinks()'を呼び出す前に処理されたことを示しているようです。だからあなたはそれを処分すべきではないか、またはそのメソッドでローカルにインスタンス化されたコンテキストを使用しているはずです。データコンテキストオブジェクトを*共有しようとすると、この問題が発生することがよくあります。 – David

+0

また、HasDota2Accountでは、dbはコンテキストと同じオブジェクトです。 dbが破棄されたときにはコンテキストも同じになります。 HasDota2Accountの呼び出しの後でコンテキストを使用しようとすると、同じ例外が発生します。 –

+0

私は最初のイメージのようにコントローラから呼び出しています。 _context_は私のコントローラ上のフィールドで、コンストラクタでインスタンス化されています。私はそれが処分されているかわからない。私はローカルの_dbcontextをインスタンス化する方法を理解しているとは思えない_なぜなら、_of startup.cs_の外で渡すことができないオプション引数をとるからです。 –

答えて

2

うん、そう:代わりに、私は渡されたコンテキスト上で直接それを呼び出すと、それが動作しますすべてのためにそれらを使用する必要があります。まず、拡張機能は、操作しているタイプへの論理接続を持つ必要があります。たとえば、stringがある場合、ToUpper()のようなものは、文字列を変更して返すため、拡張子として意味があります。あなたがしようとしているようなものがあります。参照の値を使って完全に外部の型を返すだけでは、拡張パターンに違反します。

第2に、拡張機能はデータベースのようなものとやりとりするべきではありません。特にここでは、拡張の静的性質は、EFコンテキストオブジェクトの概念とは完全に互換性がありません。あなたがそれを動作させることさえできる唯一の方法は、エクステンションが呼び出されるたびに、エクステンション内で実際に新しいコンテキストを追加することです。これは、EFオブジェクトのトラッキングに関する問題を解決する素晴らしい方法であり、メモリをリークさせる素晴らしい方法です。

長くても短くしないでください。

このコードを除外しようとしている場合は、より良い選択肢があります。たとえば、実際にコンテキストに直接メソッドを追加することができます。

public class ApplicationDbContext : DbContext 
{ 
    ... 

    public bool HasDota2Account(string id) 
    { 
     return Dota2Accounts.Any(m => m.ApplicationUserId == id); 
    } 
} 

次に、あなたのコントローラでは、あなたは単に行うことができます。

var hasDota2Account = context.HasDota2Account(User.Identity.GetUserId()); 
+0

ありがとうございます。毎日何か新しいことを学ぶ。 –

関連する問題