简体   繁体   中英

OWIN WebAPI Simple Injector EFCoreInMemoryDB injection

Im building a service using OWIN and I want to inject EF core in memory db using UserDbContext(DBOptions)

Startup.cs:

public void Configuration(IAppBuilder appBuilder)
{
    HttpConfiguration config = new HttpConfiguration();
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    var container = new Container();
    container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    // How to Register In memory DB?!
    // I get an exception on DbContextOptions< in UserContext

    container.Register<DbContext>(() => {
        var optionsBuilder = new DbContextOptionsBuilder<UserContext>()
            .UseInMemoryDatabase("UserContext");
        return new UserContext(optionsBuilder.Options);
    });

    container.Register<IUserRepository, UserRepository>();

    config.DependencyResolver =
        new SimpleInjectorWebApiDependencyResolver(container);

}

I got far enough so that I do not get an exception on starting the service. But when I call API I get an exception saying:

The constructor of type UserContext contains the parameter with name 'options' and type DbContextOptions<UserContext> that is not registered. Please ensure DbContextOptions<TUserContext> is registered, or change the constructor of UserContext

UserRepository.cs

public class UserRepository : IUserRepository
{
    private readonly UserContext context;

    public UserRepository(UserContext context)
    {
        this.context = context;
    }
}

UserContext.cs

public class UserContext : DbContext
{
    public UserContext(DbContextOptions<UserContext> options)
      : base()
    {
    }

    public DbSet<User> Users { get; set; }
}

So how do you register in ef core memory db, with UserContext using Simple Injector? It would be super easy to do this using standard .NET Core DI.

The error happens because you didn't register UserContext , but only DbContext . Change your container.Register<DbContext>(...) registration to the following:

container.Register<UserContext>(() => ...);

Also note that you currently registered the UserContext using the Transient lifestyle, while the most typical lifestyle for a DbContext is Scoped :

container.Register<UserContext>(() => ..., Lifestyle.Scoped);

It would be super easy to do this using standard .NET Core DI.

It is super easy with Simple Injector as well :) With Core DI you basically need the same registration.

The thing that confused you, is that Simple Injector v4, by default, tries to instantiate concrete unregistered dependencies for you. UserContext was not registered, while being concrete. Simple Injector tries to create it, but it found that it couldn't resolve one of its dependencies. That's why the error message points at DbContextOptions<UserContext> , instead the error being "you didn't register UserContext".

To fix this, this "resolution of unregistered concrete types" behavior will change starting from v5. v5 will, by default, not resolve unregistered concrete types any longer. This is safer and would result in a more obvious exception message.

With the introduction of Simple Injector v4.5, we introduced an option that allows you to switch to the coming v5 behavior. My advice is to use this new setting right away, as it's safer behavior and prevents you from experiencing errors once you switch to v5. You can do this as follows:

var container = new Container();

container.Options.ResolveUnregisteredConcreteTypes = false;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM