I'm still trying to get my head around what's what with ASP.NET 5 / EF 7. I'm using DNX projects (.xproj).
Startup
is used by OWIN/ASP.NET for configuring, loading services, etc. But it's also used for EF 7 migrations (to set your DbContextOptions
for example).
My main goal is to know how EF7 (and ASP.NET 5) bootstrap with Startup
and who's creating the startup class, initializing the DI container, etc.
An example of what I need to do, for context, is that in my xUnit unit tests (which are in their own assembly and reference my data assembly which doesn't have a Startup
class), I need to AddDbContext
to set my connection.
I have the sample startup class:
namespace Radar.Data
{
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
public class Startup
{
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<RadarDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
}
public void Configure(IApplicationBuilder app)
{
}
}
}
This is currently in my data assembly and not my unit test assembly. I tried adding the app setting (I know it's OWIN but I thought I'd give it a shot):
<appSettings>
<add key="owin:appStartup" value="Radar.Data.Startup, Radar.Data" />
</appSettings>
The startup class is not getting executed.
I'd really like an understanding of the overall mechanism with Startup
, who calls it, etc., but for now, I just need an understanding of how EF 7 initializes dependencies/services so that I can properly initialize my unit tests.
UPDATE Here's what I've got in my unit test so far and I thought I had it working at one point:
ServiceCollection serviceCollection = new ServiceCollection();
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
DbContextActivator.ServiceProvider = serviceProvider;
serviceCollection.AddEntityFramework()
.AddSqlServer()
.AddDbContext<RadarDbContext>(
options => options.UseSqlServer("Server=.;Database=SonOfRadar;Trusted_Connection=True;MultipleActiveResultSets=True"));
but now I'm getting No service for type 'Microsoft.Data.Entity.Internal.IDbSetInitializer' has been registered
when my DbContext
is instantiated. So obviously not getting all the EF services loaded.
If I comment out:
DbContextActivator.ServiceProvider = serviceProvider;
it errors earlier with: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.
Setting DbContextActivator.ServiceProvider
is the only place in EF7 where I can find a hook to set your own provider. I'd be just as happy getting an instance of EF7's internal service collection and working with that. I think I'm going to scour the EF7 unit test code again and see if I'm missing a critical piece.
Startup
class is created by Microsoft.AspNet.Hosting
package when you run you web application (see StartupLoader.cs).
You can also look onto WebApplication.Run
method (WebApplication.Run) its an entry point to ASP.NET 5 web applications.
DI is initialized in WebHostBuilder
class (WebHostBuilder.cs) and inside dnx
in Bootstrapper
class (Bootstrapper.cs)