Skip to content
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

Simple Injector - Injecting IDbContextScopeFactory #37

Open
wheeeels opened this issue Apr 25, 2016 · 5 comments
Open

Simple Injector - Injecting IDbContextScopeFactory #37

wheeeels opened this issue Apr 25, 2016 · 5 comments

Comments

@wheeeels
Copy link

I'm trying to inject a IDbContextScopeFactory object using Simple Injector but I'm always getting the following error:

Additional information: The configuration is invalid. Creating the instance for type IDbContextScopeFactory failed. The constructor of type DbContextScopeFactory contains the parameter with name 'dbContextFactory' and type IDbContextFactory that is not registered. Please ensure IDbContextFactory is registered, or change the constructor of DbContextScopeFactory.

My problem is that I dont see an implementation of IDbContextFactory anywhere so I'm a little lost on how to resolve this situation. Any help is appreciated

@sliekens
Copy link

sliekens commented May 12, 2016

Apparently, providing an object that implements IDbContextFactory is completely optional.

public DbContextScopeFactory(IDbContextFactory dbContextFactory = null)
{
    _dbContextFactory = dbContextFactory;
}

But as you discovered, it seems that SimpleInjector does not support constructors with defaulted parameters (in this case the default is null).

I tried explicitly registering null for service type IDbContextFactory, but that is also not supported by SimpleInjector.

You could write your own implementation and register it in your container. The default implementation can be found here:
https://github.com/mehdime/DbContextScope/blob/master/Mehdime.Entity/Implementations/DbContextCollection.cs#L64-L68

public class DefaultDbContextFactory : IDbContextFactory
{
    public TDbContext CreateDbContext<TDbContext>() where TDbContext : DbContext
    {
        return Activator.CreateInstance<TDbContext>();
    }
}

container.Register<IDbContextFactory, DefaultDbContextFactory>();

@mehdime you could improve support for dependency injection by splitting the DbContextCollection constructor into overloads with and without parameters.

// default ctor for improved support for dependency injection containers that don't support default parameters
public DbContextScopeFactory()
    : this(null)
{
}

public DbContextScopeFactory(IDbContextFactory dbContextFactory = null)
{
    _dbContextFactory = dbContextFactory;
}

@wheeeels
Copy link
Author

With that default implementation, I can now inject without any problems.
Thank you for your help!

@simon-nguyen
Copy link

simon-nguyen commented Jul 3, 2016

@wheeeels, @StevenLiekens
I am using SimpleInjector too, and the library allows me to manage the lifetime of an instance (Scoped, Transient, Singleton) when registering in an Owin WebApi 2 application. In case of DbContextScope I am currently using as below

var container = new Container();

// To allow scoped instances to be resolved during an OWIN request,
// the following registration needs to be added to the IAppBuilder instance:
app.Use(async (context, next) =>
{
    using (container.BeginExecutionContextScope())
    {
          await next();
     }
});

/**
 * There will be only one instance of a given service type within a certain (explicitly defined) scope and
 * that instance will be disposed when the scope ends(unless specified otherwise).
 * This scope will automatically flow with the logical flow of control of asynchronous methods.
 **/
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();

container.Register<IDbContextFactory, DefaultDbContextFactory>(Lifestyle.Scoped);
container.Register<IDbContextScopeFactory, DbContextScopeFactory>(Lifestyle.Scoped);
container.Register<IAmbientDbContextLocator, AmbientDbContextLocator>(Lifestyle.Scoped);

container.Register<IRepositoryAsync<User>, Repository<User>>(Lifestyle.Scoped);

container.Register<IUserService, UserService>(Lifestyle.Scoped);

container.Verify();

My question is "Does Lifestyle.Scoped suit for Owin WebApi 2 which is using DbContextScope?".

I've read that LifeStyle.Scoped will ensure the container its disposal if the type of cached instance implements IDisposable.

There's already a thread that said Singleton would make sense. But I see that you two have been using SimpleInjector so please give me some advise. Thank you.

@sliekens
Copy link

sliekens commented Jul 3, 2016

I don't know, sorry.

@rlightner
Copy link

@simon-nguyen What does your Repository class look like?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants