1

私のアプリケーションを起動して解決しようとするとうまくいきます。MVC - コンテキスト(EF)を呼び出すシンプルなインジェクタと属性例外をスローする

私はアプリケーションをデバッグし、何かを初期化してからlocalhost:81/Home/Testのような別のものを呼び出す前にブラウザのタブを閉じると、DB(EF)からデータを取得する際に例外がスローされます。

この例外は、フィルタCultureResolverの呼び出し中に発生し、LanguageServiceを呼び出します。 LanguageServiceの中には、使用可能なすべての言語を取得するためのDBへの呼び出しがあります。

ように私は、多くの異なる例外を得た:モデルが作成されている間にコンテキストを使用することはできません

  • 。この コンテキストが のOnModelCreatingメソッドの内部で使用されている場合、または複数のスレッドが同時に によって同じコンテキストインスタンスにアクセスされている場合、例外がスローされることがあります。 DbContextおよび関連するクラスのインスタンスメンバは、スレッドセーフであることは保証されていません。
  • オブジェクト参照がオブジェクトのインスタンスに設定されていません。
  • オープンしているプロバイダが、失敗しました。

これらの例外はすべて同じクエリで発生します。これは、最初のタブを実行した時間によって異なります。

だから、コンテキストが初期化される前にアイテムを取得しようとするスレッドセーフなコードやこのクエリのようです。

私は次のようました:

SimpleInjectorInitializer.cs

public static class SimpleInjectorInitializer 
{ 
    /// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary> 
    public static void Initialize() 
    { 
     var container = new Container(); 
     container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 

     InitializeContainer(container); 
     container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); 
     container.Verify(); 
     DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); 

     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters, container); 
    } 

    private static void InitializeContainer(Container container) 
    { 
     container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 

     /* Bindings... */ 

     container.RegisterPerWebRequest<IAjaxMessagesFilter, AjaxMessagesFilter>(); 
     container.RegisterPerWebRequest<ICustomErrorHandlerFilter, CustomErrorHandlerFilter>(); 
     container.RegisterPerWebRequest<ICultureInitializerFilter, CultureInitializerFilter>(); 
    } 
} 

FilterConfig.cs

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters, Container container) 
    { 
     filters.Add(container.GetInstance<ICultureInitializerFilter>()); 
     filters.Add(container.GetInstance<ICustomErrorHandlerFilter>()); 
     filters.Add(container.GetInstance<IAjaxMessagesFilter>()); 
    } 
} 

CultureResolver.cs

public class CultureResolver : ICultureResolver 
{ 
    ILanguageService Service; 
    public CultureResolver(ILanguageService Service) 
    { 
     this.Service = Service; 
    } 

    public string Resolve(string CultureCode) 
    { 
     // Get the culture by name or code (pt/pt-pt) 
     ILanguageViewModel language = Service.GetByNameOrCode(CultureCode); 

     if (language == null) 
     { 
      // Get the default language 
      language = Service.GetDefault(); 
     } 

     return language.Code; 
    } 
} 

LanguageService.cs

public class LanguageService : ILanguageService 
{ 
    IMembership membership; 
    ChatContext context; 
    ILanguageConverter converter; 

    public LanguageService(
      ChatContext context, 
      IMembership membership, 
      ILanguageConverter converter 
     ) 
    { 
     this.membership = membership; 
     this.context = context; 
     this.converter = converter; 
    } 

    public virtual ILanguageViewModel GetByNameOrCode(string Text) 
    { 
     string lowerText = Text.ToLower(); 
     string lowerSmallCode = ""; 

     int lowerTextHiphen = lowerText.IndexOf('-'); 
     if (lowerTextHiphen > 0) 
      lowerSmallCode = lowerText.Substring(0, lowerTextHiphen); 

     Language item = this.context 
          .Languages 
          .FirstOrDefault(x => x.Code.ToLower() == lowerText 
               || x.SmallCode.ToLower() == lowerText 
               || x.SmallCode == lowerSmallCode); 
     return converter.Convert(item); 
    } 

    public virtual ILanguageViewModel GetDefault() 
    { 
     Language item = this.context 
          .Languages 
          .FirstOrDefault(x => x.Default); 
     return converter.Convert(item); 
    } 
} 

は、これは私のMVCとWeb APIで

Language item = this.context 
        .Languages 
        .FirstOrDefault(x => x.Code.ToLower() == lowerText 
             || x.SmallCode.ToLower() == lowerText 
             || x.SmallCode == lowerSmallCode); 

答えて

1

グローバルフィルタはシングルトンある例外を与えているクエリです。アプリケーションの存続期間中は、そのようなフィルタのインスタンスは1つだけです。あなたは一度コンテナからフィルタを解決し、容器の寿命のためにそれを保存ここで

filters.Add(container.GetInstance<ICultureInitializerFilter>()); 

:あなたは以下のコードを見たときにこれが明らかになりました。

ます。ただし、使用してScopedとしてこのタイプを登録している:

container.RegisterPerWebRequest<ICultureInitializerFilter, CultureInitializerFilter>(); 

をあなたが効果的にされていない、そのクラスがDbContextに依存しているため、最も可能性の高い、Web要求ごとに1つのインスタンスが存在すべきであると言っていますスレッドセーフです。

フィルタに依存関係を持たせるには、humble objectsにするか、呼び出すことのできる謙遜なオブジェクトに入れてください。

filters.Add(new GlobalActionFilter<ICultureInitializerFilter>(container)); 
filters.Add(new GlobalActionFilter<ICustomErrorHandlerFilter>(container)); 
filters.Add(new GlobalActionFilter<IAjaxMessagesFilter>(container)); 

GlovalActionFilter<T>を容器にコールバックされますが、指定された型のすべてを解決するために:

public sealed class GlobalActionFilter<TActionFilter> : IActionFilter 
    where TActionFilter : class, IActionFilter 
{ 
    private readonly Container container; 
    public GlobalActionFilter(Container container) { this.container = container; } 

    public void OnActionExecuted(ActionExecutedContext filterContext) { 
     container.GetInstance<TActionFilter>().OnActionExecuted(filterContext); 
    } 

    public void OnActionExecuting(ActionExecutingContext filterContext) { 
     container.GetInstance<TActionFilter>().OnActionExecuting(filterContext); 
    } 
} 

このクラスは、次のようにあなたのグローバルフィルタを追加することができます:たとえば、次のアクションフィルタを作成することができますそれが呼び出される時間。これにより、依存関係が発生している問題を防ぐcaptiveになるのを防ぎます。

+0

ロック!しかし、それは私がそれを避けるので、 "シングルトン"という言葉を何度も使って間違っているようです。私はその1つを試してみましょう –

+0

しかし、私はあなたが与えたコードを使用しようとしていますが、そのような述語を使用する方法を知らない、それはちょうど私にコンパイルエラーを与える –

+0

@LeandroSoares:あなたはまだC#5(あなたは貧しい魂;-)を使用しています。単に "=>"を "{"に置き換え、終了する "}"をメソッドに追加してください。 – Steven

関連する問題