New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Context without DI? #2718
Comments
@RickStrahl You can derive from DbContext and then just use 'new' to create an instance of your context, just like you could in older versions of EF. EF will still use DI to manage its own services, but it will be a separate container isolated from the rest of your application. UseSqlServer just requires a connection string, which can be obtained in any way you want. In your sample code you are using ConfigurationBuilder. This is not an EF component and I don't know if it can be used independently of DI or not. @divega might know more. But you certainly don't need to use ConfigurationBuilder or any of its related classes in order to use EF. |
Right I get that. My issue is that in order to build a self-contained context we typically need access to the configuration in some way. In the past we've always been able to get at configuration through the global objects, but now everything is supposed to be injected removing the ability to self-configure easily. The workaround for now is to use the IServiceProvider overload which requires DI and that works OK for top level code that has access to that. But if you're inside of a component there's no guarantee that you can get at IServiceProvider... What are the recommendations for dealing creating contexts inside of other components - like a business layer, or even more generically in a repository like framework? Should you then set up your own configuration that passes those things in 'globally'? |
@RickStrahl When you say, "The workaround for now is to use the IServiceProvider overload" do you mean the IServiceProvider overload of DbContext or of something else? Using the IServiceProvider overload of DbContext should not be required here or have any impact on this. EF is never going to read from configuration directly anyway. EF doesn't integrate with the configuration system at all--you get your connection string in any way you want and give it to EF, and that is true however you use EF, with an external DI container or not. If the way DNX configuration is tied to DI doesn't work for you, then you might want to try posting in the Configuration repro: https://github.com/aspnet/Configuration |
@ajcvickers - if you pass in IServiceProvider, EF will create the instance with the configuration info from the top level configuration applied. So in say a controller this works if IServiceProvider is injected: using (var ctxt = new AlbumViewerContext(serviceProvider))
{
... this works
} But, this gets more complicated when you're inside of a component that has no knowledge of the top level application and may not have access to IServiceProvider (or any other DI created components for that matter). |
@RickStrahl "if you pass in IServiceProvider, EF will create the instance with the configuration info from the top level configuration applied" EF doesn't do this. It used to do it in beta3, maybe beta4. But then all the configuration integration was removed from EF and it is now up to the application to read configuration in any way that makes sense to the application and then pass it to EF. |
@RickStrahl another option is just to make Startup.Configuration static (I did this in an app where I wanted to be able to access config without having to get it from DI). It's always initialized as part of startup, so it should always be available when you need it. |
The problem is you have to do that at the Application level not the component level. My thinking here is how to get at configuration from within a custom, generic component that might be used by many different applications. |
@ajcvickers - It works for me in Beta 5. If I do this ins using ide of a controller I get a configured instance: using (var ctxt = new AlbumViewerContext(serviceProvider))
{ } So somehow EF is pulling the configuration information out of the service provider instance. |
If you can't set a connectionstring without using DI, there's a problem. |
@blakeholl you can totally use EF without DI, in fact outside of ASP.NET 5 that is the default pattern we recommend folks use - here is a sample from our docs http://ef.readthedocs.org/en/latest/getting-started/full-dotnet.html. |
Yes, I have seen that wiki. I just think it's a bit of a hassle that I have to write a lot of implementation details (adding a constructor and _connectionString field, and override OnConfiguring) into my DbContext subclass to support setting a connection string programmatically. I still feel like nhibernate has the better configuration model. Thanks anyway @rowanmiller |
@blakeholl you can also just take a |
Just had to work with this scenario myself and I see @rowanmiller's link is broken. Here is a sample of what I did in my
Honestly, a lot of apps are so small or simple that they will never need this, and even if they do, this isn't very much work. It allows me to run |
@tuespetre It's been a while since I worked on this, but if I recall this only works if you already have configured your app. If there's no configuration set up (yet?) the ConfigurationBuilder() will not know where to get the connection string from for example. It all hinges on pre-configuration. To me this is MUCH MUCH worse than what we had with web.config, because at least with that it worked as long as the setting were there. Now, you are depending on the configuration of the application to be configured in a very specific way or else self-configuration just doesn't work. Again at the Application level this is not a problem - it's more of a problem for a component/middle tier object that needs to be able to self-configure to load into different environments without dependencies on a specific configuration setup. |
Relying on In the example I placed above, I am just grabbing an environment variable for the connection string. If you wanted to use a config file, you could try something like this:
Environment variables or JSON -- either way, no |
@tuespetre My point is that you can't rely on that in a generic component. Because there's no one single place that configuration comes from or at least is not guaranteed to be there you can't assume anything. Again this works fine in application scenarios, but it's a major pain for component configuration where a component has to work in any environment and there are no real standards or even config file layout rules. |
@RickStrahl totally get your problem, the issue is that there is no static/global configuration (i.e. ConfigurationManager). I don't think there is really anything we can do in EF since we run in different app environments that have different configuration models (i.e. Console/WinForms/ASP.NET 4 etc. all have ConfigurationManager but ASP.NET Core use the non-global cc @divega as he owns Configuration in "Core World" |
Just reading through discussion issues that has been sitting on my plate for a long time and trying to see if there is anything actionable. It seems many of the EF Core related concerns mentioned in the thread been addressed by improvements, e.g.:
The only outstanding issue seems to be the desire that the ASP.NET Core stack defined some static/global configuration mechanism which generic components can rely on always being present. Although this is valid feedback (there is a tradeoff which leads to some loss of functionality of convenience) lack of such a static/global mechanism for configuration (or any other static/global mechanism for that matter) was actually a deliberate design decision by the ASP.NET team to favor designs that are more explicit about how configuration is passed and that are more testable. |
If we want to create a fully self-configuring DbContext that doesn't depend on DI, what's the best way to do this?
In the previous beta I was able to access the Configuration instance directly and read the connectionstring info explicitly. However, in the current beta the configuration object appears that it needs a base path which has to come - from DI.
Here's what I would roughly like to be able to do:
My primary reason for this is that I'm not a fan of injected and scoped DbContext instances. In many applications I work on we often deal with multiple contexts in a single controller that aren't used by all actions. There's extra overhead for instantiating these instance, plus there are also few odds and ends where you need multiple contexts in order to keep multiple db operations isolated even when working against the same context type.
Anyway - in the past with EF 6 I typically build a self configuring context that runs off the parameterless constructor. Typically the code to set this up simply points at a connection strings entry and the rest is handled. I'd like to be able to do the same in EF7 as an alternative to feeding a configured instance through DI.
The text was updated successfully, but these errors were encountered: