Inject DbContext in Asp.Net Core. Concrete type or interface? - asp.net-core

On an Asp.Net Core project I am injecting Entity Framework DbContext:
public MessageRepository(MyDbContext context) {
}
And the configuration is:
services
.AddEntityFramework()
.AddSqlServer()
.AddDbContext<Context>(x => x.UseSqlServer(connectionString);
Should I create an interface, IMyDbContext, and injecting it instead?
public class MyDbContext : DbContext, IMyDbContext { }
public MessageRepository(IMyDbContext context) {
}
In all ASP.NET Core examples I see the concrete type, MyDbContext, is being injected and not an interface ...
What option should I choose?

Currently working on a project myself, where I decided to go with 2 interfaces like this
public interface IDbContext : IDisposable
{
DbContext Instance { get; }
}
and
public interface IApplicationDbContext : IDbContext
{
DbSet<MyEntity> MyEntities { get; set; }
...
}
My concrete DbContext would then just implement the application context interface
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
public DbContext Instance => this
public DbSet<MyEntity> MyEntities { get; set; }
}
This allows my implementation of the Application context to be injected as the application context interface, while also providing me access to the DbContext methods through the Instance property getter without having to add methods needed from the DbContext class to the interface.
Until now, this works great.

We're always injecting an interface, since it's easier to mock in unit and integration tests.
Are you willing to change the signature of the MessageRepository constructor? It relies on the concrete type.
Do you write tests for your code? Using and interface would make it easier to mock the database context.
If you've answered "no" to one or more of the above, inject the concrete type; otherwise, inject the interface.
[EDIT]
use the following.
context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

In my opinion, you should always rely on an interface as #Uli said, but when it comes to the DbContext you need to take in mind that you are exposing all methods of the DbContext of EntityFramework Core
public class MyDbContext : DbContext, IMyDbContext { }
in that case, you don't need to implement any method that you are exposing because DbContext handles that for you.
BUT if EF code change the DbContext and you make an update to your project then you will be on a painful situation of updating your IMyDbContext every time, also all your unit testing. In my opinion, that will give you a lot of headaches.
This answers/questions can help you to understand why https://stackoverflow.com/a/6768712/819153
Unit testing EF - how to extract EF code out from BL?

Related

Dependency Injection with Database-Context. How to get Database-Context in a normal Class

I have configured my .net-core 2.1 service with a database-context in the start-up method.
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString(nameof(DatabaseContext))));
Now i could do the following to get my database-context in my controller:
var context = serviceProvider.GetService<DatabaseContext>();
This works very well. But how could i access the Database-Context in a normal class something like this sould be done:
public class MyAccessClass{
public MyAccessClass(){
//Access the ServiceProvider or get the Database-Context class anywhere else
}
}
I don't want to pass the database-context object through the constructor or to initialize the DatbaseContext Class again.
Thanks for your help.
You should take your dependencies through the constructor, preferrably an interface, e.g. IDatabaseContext, but code sample below based on your code. If you add MyAccessClass as a service, e.g. services.AddTransient<MyAccessClass>(), and then use dependency injection in your controller, the database context would be automatically injected in the constructor by the default IoC container in ASP.NET Core.
You shouldn't have it rely on IServiceProvider, the reasoning is that your class wants to make no assumption of implementations, it just needs the database context. Having it rely on IServiceProvider would assume this context, and any possible future dependencies, comes from the IoC in ASP.NET Core which may not be the case (what if you just want to release this as a class library later on?). It would make the MyAccessClass class hard to test and use outside of a controller.
You say in your comment:
"...or get the Database-Context class anywhere else"
That anywhere else is completely flexible by simply accepting the context into the constructor since your class doesn't know where anywhere else is but whatever is creating your class does know!
Example of DI in ASP.NET Core
Take context as a dependency through constructor
public class MyAccessClass{
private readonly DatabaseContext databaseContext;
public MyAccessClass(DatabaseContext databaseContext) {
this.databaseContext = databaseContext;
}
}
Add as service
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<MyAccessClass>();
}
Inject into a controller
public class MyController : Controller
{
private readonly MyAccessClass myAccessClass;
//Happily injected through DI
public MyController(MyAccessClass myAccessClass)
{
this.myAccessClass = myAccessClass;
}
}
Or inject straight into an action
public class MyController : Controller
{
public MyController()
{
}
public IActionResult MyAction([FromServices] MyAccessClass myAccessClass)
{
}
}

NHibernate, injecting service into IUserType using .NET Core ioc container

Is it possible to inject a service into a UserType ?
internal class MyUserType : IUserType
{
private static ISerializer _serializer;
public MyUserType (ISerializer serializer)
{
_serializer = serializer
}
}
Tried the why it is suppose to work for all but fails, stating it needs a default parameterless constructor
I don't think this is going to be possible as you would need to tap into NH's component creation pipeline/process, which, AFAIK, isn't readily exposed.
You could use property injection with a 'local default'. This would allow you to depend on the ISerializer abstraction and replace it when necessary, testing maybe, but rely on a default concrete type in an environment that didn't support IoC.
internal class MyUserType : IUserType
{
private static ISerializer _serializer = new ConcreteSerializer();
public JsonShippingDetailsUserType()
{
}
public ISerializer Serializer { get; set; }
}
N.B. This is a really naive implementation of property injection. If you go with this solution you'll need to 'harden' the code. Mark Seemann's DI book has an excellent example.
The thing is that IUserType is managed by NHibernate which uses its own IoC container and by implication does not have access to your IoC of choice and again by implication does not have access to any services registered on your IoC of choice. There is not easy way of injecting, what I can think of is some sort of proxy or to somehow get access to NHibernate internals.

Using Ninject with mocks in F#

This question is part of larger question that can be found here
As in out production code we use Ninject and constructor injection our services tend to look like this
public class Service : IService
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
public Task<IEnumerable<SelectOption>> GetAlLogicOptions()
{
return _repository.GetOptionsAsync();
}
}
how ever list of constructor parameters may and will change over time. This is the reason that we want to have IoC to also be used in tests.
In C# NUnit this is quite easy as we have Ninject.MockingKernel that always provides mock implementation and in each test fixture we just rebind sut to it real implementation.
How to achieve same thing in F# xUnit.

Ninject NHibernate on plugin oriented architecture

According COMPOSITION ROOT pattern, I must to construct all dependencies graph as close as possible to the application's entry point.
My architecture is plugin oriented. So, if someone wants to extend my base system he can.
For example, in my base system I have this structure:
View Layer
Services Layer
Data Access Layer
Model Layer
In DAL, I expose some classes like:
IRepository
NHibernateRepository
ProductRepository
So, I'd like if a plugin wants to extend my base Product class to ExtendedProduct, and then create ExtendedProductRepository that inherits from NHibernateRepository.
The question is:
How can instantiate from my base system an instance of NHibernateRepository using NInject?
So, I know the first thing to do is to construct the graph dependencies:
using (var kernel = new StandardKernel())
{
kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom<IRepository>()
.BindAllInterfaces());
}
However, I'm figuring out that when I execute something like:
kernel.GetAll<IRepository>()
It's going to return me a ProductRepository instance, and another ProductExtendedRepository under two IRepository objects.
So, how I can save a ProductExtended object from my base system...?
Another question, would be, how could I inject a object instance in my plugins, or, how can plugins autoinject some instance of base system assembly?
Thanks for all.
I'll appreciate a lot some help.
I use this pattern for my NHibernate based projects:
public interface IRepository<T> : IQueryable<T>
{
T Get(int id);
void Save(T item);
void Delete(T item);
}
public class NHibernateRepository<ModelType> : IRepository<ModelType>
where ModelType : class
{
// implementation
}
then...
public interface IProductRepository : IRepository<Product>
{
// product specific data access methods
}
public class ProductRepository : NHibernateRepository<Product>, IProductRepository
{
// implementation
}
... and in Ninject Module:
Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>));
Bind<IProductRepository>().To<ProductRepository>();
then you can either request the base functionality like:
public Constructor(IRepository<Product> repo) { ... }
or specific product repository functionality:
public Constructor(IProductRepository repo) { ... }
your plugins can either get the base functionality and won't have to register anything:
public PluginConstructor(IRepository<ProductExtended> repo { ... }
or create their own repositories and register them in a Ninject module.
Thanks dave.
It's perfect. I'll try it.
However, how could I save or get or update (whichever IRepository methods)... an ExtendedProduct instance from my base system?
Think the follow out:
public interface BasePlugin<T> {...}
In another assembly:
public class PluginExtendedProduct : BasePlugin<ExtendedProduct>
{
public PluginExtendedProduct (IRepository<ExtendedProduct> repo { ... }
}
My headache is how to create an instance of (so, ExtendedProduct) in my base system in order to call methods PluginExtendedProduct that uses an IRepository.
I don't know if I'm explaining myself well...
Thanks for all.

Using Ninject to bind an interface to multiple implementations unknown at compile time

I just recently started using Ninject (v2.2.0.0) in my ASP.NET MVC 3 application. So far I'm thrilled with it, but I ran into a situation I can't seem to figure out.
What I'd like to do is bind an interface to concrete implementations and have Ninject be able to inject the concrete implementation into a constructor using a factory (that will also be registered with Ninject). The problem is that I'd like my constructor to reference the concrete type, not the interface.
Here is an example:
public class SomeInterfaceFactory<T> where T: ISomeInterface, new()
{
public T CreateInstance()
{
// Activation and initialization logic here
}
}
public interface ISomeInterface
{
}
public class SomeImplementationA : ISomeInterface
{
public string PropertyA { get; set; }
}
public class SomeImplementationB : ISomeInterface
{
public string PropertyB { get; set; }
}
public class Foo
{
public Foo(SomeImplementationA implA)
{
Console.WriteLine(implA.PropertyA);
}
}
public class Bar
{
public Bar(SomeImplementationB implB)
{
Console.WriteLine(implB.PropertyB);
}
}
Elsewhere, I'd like to bind using just the interface:
kernel.Bind<Foo>().ToSelf();
kernel.Bind<Bar>().ToSelf();
kernel.Bind(typeof(SomeInterfaceFactory<>)).ToSelf();
kernel.Bind<ISomeInterface>().To ...something that will create and use the factory
Then, when requesting an instance of Foo from Ninject, it would see that one of the constructors parameters implements a bound interface, fetch the factory, and instantiate the correct concrete type (SomeImplementationA) and pass it to Foo's constructor.
The reason behind this is that I will have many implementations of ISomeInterface and I'd prefer to avoid having to bind each one individually. Some of these implementations may not be known at compile time.
I tried using:
kernel.Bind<ISomeInterface>().ToProvider<SomeProvider>();
The provider retrieves the factory based on the requested service type then calls its CreateInstance method, returning the concrete type:
public class SomeProvider : Provider<ISomeInterface>
{
protected override ISomeInterface CreateInstance(IContext context)
{
var factory = context.Kernel.Get(typeof(SomeInterfaceFactory<>)
.MakeGenericType(context.Request.Service));
var method = factory.GetType().GetMethod("CreateInstance");
return (ISomeInterface)method.Invoke();
}
}
However, my provider was never invoked.
I'm curious if Ninject can support this situation and, if so, how I might go about solving this problem.
I hope this is enough information to explain my situation. Please let me know if I should elaborate further.
Thank you!
It seems you have misunderstood how ninject works. In case you create Foo it sees that it requires a SomeImplementationA and will try to create an instance for it. So you need to define a binding for SomeImplementationA and not for ISomeInterface.
Also most likely your implementation breaks the Dependency Inversion Princple because you rely upon concrete instances instead of abstractions.
The solution to register all similar types at once (and the prefered way to configure IoC containers) is to use configuration by conventions. See the Ninject.Extensions.Conventions extenstion.