1

BaseController に、LINQ to SQL データ コンテキスト (またはテスト用の偽のコンテキスト) を保持する DataContext というプロパティがあります。パラメーターなしのコンストラクターを使用する場合 (つまり、ASP.NET MVC への要求が行われる場合)、LINQ to SQL データ コンテキストの新しいインスタンスがプロパティに割り当てられます。

public class BaseController : Controller {
    public IDataContextWrapper DataContext { get; set; }

    public BaseController() : this(new DataContextWrapper<MyDataContext>()) { }

    public BaseController(IDataContextWrapper context) {
        DataContext = context;
    }
}

また、BaseController で、いくつかのグローバル ViewData 項目を設定しました。

protected override void OnActionExecuting(ActionExecutingContext filterContext) {
    ViewData["Example"] = DataContext.Table<Example>().Count();
    base.OnActionExecuting(filterContext);
}

これは、ほとんどすべてのアクションでうまく機能しています。機能しない唯一のものは、私の AccountController の Logout アクションです。

public ActionResult Logout() {
    FormsAuth.SignOut();
    return RedirectToResult("Login");
}

これにより、BaseController.OnActionExecuting 中に NullReferenceException が発生します。その特定のアクションを実行すると、DataContext プロパティは null になります。

これが 1 つのアクションでのみ発生するのはなぜですか?

注: IDataContextWrapper と DataContextWrapper は、LINQ to SQL DataContext オブジェクトの既存の機能をラップするだけなので、単体テストで偽のコンテキストに置き換えることができます。独自に破棄することはありませんが、基礎となる DataContext に任せているので、それは問題ではないと確信しています。

4

2 に答える 2

1

私のコメントをフォローアップするには、このリンクを確認してください。具体的には、次の状態の Microsoft ドキュメントのリンクを確認してください。

一般に、DataContext インスタンスは 1 つの「作業単位」の間存続するように設計されていますが、アプリケーションではその用語を定義しています。DataContext は軽量で、作成に費用がかかりません。一般的な LINQ to SQL アプリケーションは、メソッド スコープで、または関連するデータベース操作の論理セットを表す有効期間が短いクラスのメンバーとして、DataContext インスタンスを作成します。

Microsoft はこれを説明するのにひどい仕事をし、そもそも n 層環境で Linq を使用することを率直に説明しました。私の特定のケースでは、Singleton パターンを介して実装された 1 つの (静的) データコンテキストがありました。(それは最も論理的な設計であるため、IMHO )。ただし、これは物事を行う方法ではありません。私の場合、静的インスタンスを返す代わりに、毎回新しい DataContext を返すように GetDataContext() 呼び出しを変更することで、修正は実際には非常に簡単でした。ただし、これにより、まったく新しい問題が発生することがわかります。それらを理解すれば、克服できないものはありませんが、間違いなく苦痛です.

そのような設定 (DataContext の Singleton アクセサー) がある場合は、それを変更して問題が解決するかどうかを確認してください。

いずれにせよ、n 層アーキテクチャを扱う場合は、グローバル DataContext を使用したり、DataContext を保持したりしないでください。

これで特定の問題が解決しない場合でも、ソリューションを再構築して、DataContexts に作業単位の寿命を持たせることを強くお勧めします。

于 2009-06-09T23:27:42.790 に答える
0

よくわからない理由で、ログアウトアクション用に新しいAccountControllerが作成されると、ASP.NET MVCはnullパラメーターを持つ2番目のコンストラクターを使用します(バグの可能性がありますか?)。パラメータがnullの場合に、新しいデフォルトのDataContextを作成するようにクラスを変更しました。

public class BaseController : Controller {
    public IDataContextWrapper DataContext { get; set; }

    public BaseController() : this(null) { }

    public BaseController(IDataContextWrapper context) {
        DataContext = dataContext ?? new DataContextWrapper<MyDataContext>();
    }
}

今では動作します。

ASP.NET MVCがデフォルトのコンストラクターを使用する場合もあれば、オーバーロードを使用する場合もあるのは不思議なことです。誰かがこれに光を当てることができますか?

于 2009-06-09T23:45:11.303 に答える