2017-05-25 14 views
22

मुझे निम्नलिखित अपवाद प्राप्त होता है जब मैं Startup.cs फ़ाइल में Configure विधि में कस्टम DbContext का उपयोग करने का प्रयास करता हूं। मैं संस्करण 2.0.0-preview1-005977 में ASP.NET कोर का उपयोगएएसपी.नेट कोर 2 में निर्भरता इंजेक्शन अपवाद

बिना क्रिया के अपवाद: System.Exception: प्रकार की एक सेवा पैरामीटर के लिए 'Communicator.Backend.Data.CommunicatorContext' को हल नहीं कर सका dbContext ' 'Communicator.Backend.Startup' प्रकार पर 'कॉन्फ़िगर करें' विधि का। ---> System.InvalidOperationException: रूट प्रदाता से स्कोप्ड सेवा 'Communicator.Backend.Data.CommunicatorContext' को हल नहीं कर सकता।

जब मैं अन्य उदाहरण प्राप्त करने का प्रयास करता हूं तो यह अपवाद भी फेंक दिया जाता है।

बिना क्रिया के अपवाद: System.Exception: के प्रकार 'Communicator.Backend.Services.ILdapService' ...

यहाँ मेरी ConfigureServices और Configure तरीकों एक सेवा को हल नहीं कर सका।

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 
    services.AddCookieAuthentication(); 
    services.Configure<LdapConfig>(Configuration.GetSection("Ldap")); 
    services.AddScoped<ILdapService, LdapService>(); 
    services.AddMvc(); 
} 

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CommunicatorContext dbContext, ILdapService ldapService) 
{ 
    app.UseAuthentication(); 
    app.UseWebSockets(); 
    app.Use(async (context, next) => 
    { 
     if (context.Request.Path == "/ws") 
     { 
      if (context.WebSockets.IsWebSocketRequest) 
      { 
       WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); 
       await Echo(context, webSocket); 
      } 
      else 
      { 
       context.Response.StatusCode = 400; 
      } 
     } 
     else 
     { 
      await next(); 
     } 
    }); 
    app.UseMvc(); 
    DbInitializer.Initialize(dbContext, ldapService); 
} 

उत्तर

40

का हवाला देते हुए प्रलेखन

Services Available in Startup

ASP.NET कोर निर्भरता इंजेक्शन एक आवेदन के स्टार्टअप के दौरान आवेदन सेवाएं प्रदान करता है। आप को अपने Startup कक्षा के कन्स्ट्रक्टर या Configure या ConfigureServices विधियों में से एक पैरामीटर के रूप में उचित इंटरफ़ेस सहित इन सेवाओं का अनुरोध कर सकते हैं।

  • निर्माता में: IHostingEnvironment, ILoggerFactory
  • में

    जिस क्रम में वे कहा जाता है में Startup कक्षा में प्रत्येक विधि को देखते हुए, निम्नलिखित सेवाओं पैरामीटर के रूप में अनुरोध किया जा सकता ConfigureServices विधि: IServiceCollection

  • Configure विधि में: IApplicationBuilder, IHostingEnvironment, 012,, IApplicationLifetime

आप सेवाओं है कि स्टार्टअप के दौरान उपलब्ध नहीं हैं को हल करने की कोशिश कर रहे हैं,

...CommunicatorContext dbContext, ILdapService ldapService) { 

जो आप त्रुटियों मिल रहा है दे देंगे। आप कार्यान्वयन के लिए उपयोग की जरूरत है तो आप निम्न में से एक कार्य करना होगा:

  1. संशोधित ConfigureServices विधि और उन्हें सेवा संग्रह से वहाँ तक पहुँचने। अर्थात।

    public IServiceProvider ConfigureServices(IServiceCollection services) { 
        services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 
        services.AddCookieAuthentication(); 
        services.Configure<LdapConfig>(Configuration.GetSection("Ldap")); 
        services.AddScoped<ILdapService, LdapService>(); 
        services.AddMvc(); 
    
        // Build the intermediate service provider 
        var serviceProvider = services.BuildServiceProvider(); 
    
        //resolve implementations 
        var dbContext = serviceProvider.GetService<CommunicatorContext>(); 
        var ldapService = serviceProvider.GetService<ILdapService>(); 
        DbInitializer.Initialize(dbContext, ldapService); 
    
        //return the provider 
        return serviceProvider(); 
    } 
    
  2. संशोधित IServiceProvider वापस जाने के लिए ConfigureServices विधि, Configure विधि लेने के लिए एक IServiceProvider और फिर वहाँ अपने निर्भरता को हल। अर्थात न्कोसी से

    public IServiceProvider ConfigureServices(IServiceCollection services) { 
        services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 
        services.AddCookieAuthentication(); 
        services.Configure<LdapConfig>(Configuration.GetSection("Ldap")); 
        services.AddScoped<ILdapService, LdapService>(); 
        services.AddMvc(); 
    
        // Build the intermediate service provider then return it 
        return services.BuildServiceProvider(); 
    } 
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
             ILoggerFactory loggerFactory, IServiceProvider serviceProvider) { 
    
        //...Other code removed for brevity 
    
        app.UseMvc(); 
    
        //resolve dependencies 
        var dbContext = serviceProvider.GetService<CommunicatorContext>(); 
        var ldapService = serviceProvider.GetService<ILdapService>(); 
        DbInitializer.Initialize(dbContext, ldapService); 
    } 
    
+0

मैंने पहला बदलाव किया और यह काम करता है। धन्यवाद –

+0

धन्यवाद, यह मेरी समस्या हल करता है। यदि मैं दोनों विकल्पों का परीक्षण करने के बाद और अधिक जोड़ सकता हूं, तो मुझे पता चला कि काम करने के दूसरे विकल्प के लिए मुझे 'IServiceProvider' वापस करने के लिए 'void' (डिफ़ॉल्ट रूप से) लौटने से' कॉन्फ़िगर सर्विसेज 'को संशोधित करने की आवश्यकता है। – muhihsan

18

समाधान क्योंकि services.BuildServiceProvider() खुद के लागू मानकों आप validateScopes गुजर नहीं कर रहे हैं के बिना काम करता है। चूंकि यह सत्यापन अक्षम है अपवाद नहीं फेंक दिया गया है। इसका मतलब यह नहीं है कि समस्या नहीं है।

ईएफ कोर DbContext स्कॉप्ड लाइफस्टाइल के साथ पंजीकृत है। एएसपी देशी डी कंटेनर स्कोप में IServiceProvider के उदाहरण से जुड़ा हुआ है। आम तौर पर जब आप नियंत्रक से अपने DbContext का उपयोग करते हैं तो कोई समस्या नहीं है क्योंकि एएसपी प्रत्येक अनुरोध के लिए नया स्कोप (IServiceProvider का नया उदाहरण) बनाता है और फिर इस अनुरोध के भीतर सब कुछ हल करने के लिए इसका उपयोग करता है। हालांकि आवेदन स्टार्टअप के दौरान आपके पास अनुरोध का दायरा नहीं है। आपके पास IServiceProvider का उदाहरण है जो स्कॉप्ड नहीं है (या रूट स्कोप में दूसरे शब्दों में)। इसका मतलब है कि आपको अपना दायरा बनाना चाहिए। आप इसे इस तरह कर सकते हैं:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>(); 
    using (var scope = scopeFactory.CreateScope()) 
    { 
     var db = scope.ServiceProvider.GetRequiredService<CommunicatorContext>(); 
     var ldapService = scope.ServiceProvider.GetRequiredService<ILdapService>(); 
     // rest of your code 
    } 
    // rest of Configure setup 
} 

ConfigureServices विधि में कोई बदलाव नहीं कर सकते हैं।

संपादित

आपका समाधान बिना किसी परिवर्तन के 2.0.0 आरटीएम में काम करेंगे में के बाद से आरटीएम scoped सेवा प्रदाता कॉन्फ़िगर विधि https://github.com/aspnet/Hosting/pull/1106 के लिए बनाया जाएगा।

13
.UseDefaultServiceProvider(options => 
      options.ValidateScopes = false) 

इस वैकल्पिक रूप से के लिए मुझे

Documentation Here

4

के बाद .UseStartup<Startup>()


वर्क्स Program.cs में जोड़ने के लिए, यदि आप अपने Configure विधि के भीतर एक सेवा गुंजाइश बना सकते हैं:

var scopeFactory = ApplicationServices.GetService<IServiceScopeFactory>(); 
using (var scope = scopeFactory.CreateScope()) 
{ 
    var dbContext = scope.ServiceProvider.GetService<CommunicatorDbContext>(); 
    DbInitializer.Initializer(dbContext, ldapService); 
} 

आप बस, scoped सेवा आप Configure निर्माता में जरूरत इंजेक्षन कर सकते हैं, के रूप में स्लैक पर उल्लेख किया है, इस ;-)

+1

इसमें क्या गलत है? आप ऐसा क्यों नहीं करने का सुझाव देते हैं। मेरे पास अब यह है: ''' '(var scope = app.AplicationServices.CreateScope()) स्कोप। सेवाप्रोवाइडर। गेट सेवा ()। InitAsync()। प्रतीक्षा करें();' '' क्या मुझे यह कुछ और तरीका करना चाहिए ? – Ciantic

13

ASP.NET कोर 2.0 आरटीएम में ऐसा नहीं करते हैं जैसे आप शुरू में करने की कोशिश की:

public void Configure(
    IApplicationBuilder app, 
    IHostingEnvironment env, 
    ILoggerFactory loggerFactory, 
    CommunicatorContext dbContext, 
    ILdapService ldapService) 
{ 
    // ... 
} 

#1106 में सुधार के लिए धन्यवाद, यह बहुत आसान है।

+0

प्रश्न की समस्या को हल करने का यह प्राकृतिक तरीका है। धन्यवाद। – harveyt

+0

2.0 आरटीएम के साथ ऐसा करने का सबसे अच्छा तरीका – Postlagerkarte

संबंधित मुद्दे