DbContext and Ninject - ninject

I just read some articles that DbContext should not be cached, so I'd like to check if this will be an concern when using it together with Ninject (or any other similar library).
Generally speaking, will Ninject use some kind of caching techniques?
Bind<IEntityService<Log>>().To<EntityService<Log>>();
where EntityService has a private dbContext reference.
class EntityService
{
private DbContext _dbContext;
}
Thanks

Ninject should not use any caching if do not specify it.
If the tree of your injected objects is not cached or isn't used in some scope (singleton or per request) then each time when you resolve your reference you should have the new instance of your context.

Related

ASP.Net Core Open Partial Generic Dependency Injection

I would like to register the following items for DI using an open generic implementation and interface. I know the following example will not work, as well as other combinations I've tried with MakeGenericType, or GetGenericArguments. I would like to simply call AddRepository<MyDbContext> and then be able to inject my implementation into classes without explicitly having to register the type I am using.
Interface
public interface IRepository<TEntity>
{
}
Implementation
public class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
}
Registration
public static class RepositoryServiceCollectionExtensions
{
public static IServiceCollection AddRepository<TContext>(
this IServiceCollection services) where TContext : DbContext
{
services.TryAddScoped(
typeof(IRepository<>),
typeof(Repository< , TContext>));
return services;
}
}
The dependency injection container Microsoft.Extensions.DependencyInjection and its abstraction layer does not support open generic factories. So you generally cannot achieve what you would like to do there. There’s also no support planned.
Unlike many those other dependency injection related features, this is also not really possible to patch by just providing the right wrapper or factory types. So you will actually have to change your design here.
Since you want to resolve IRepository<TEntity> and the only way to do this is by registering an equivalent open generic type, you will have to have some type Repository<TEntity> that implements your repository. That makes it impossible to retrieve the database context type from the generic type argument, so you will have to use a different way here.
You have different options to do that. For example, you could configure your Repository<TEntity> (e.g. using M.E.Options) with the context type and make that resolve the Repository<TEntity, TContext> dynamically. But since you have actual control over your database context, I would suggest either adding a marker interface or introducing another type for the context which you can then register with the container:
public class Repository<TEntity> : IRepository<TEntity>
{
public Repository(IDbContext dbContextFactory)
{ … }
}
public class MyDbContext : DbContext, IDbContext
{ … }
Then, your extension method could look like this:
public static IServiceCollection AddRepository<TContext>(this IServiceCollection services)
where TContext : DbContext, IDbContext
{
services.AddTransient(typeof(IDbContext), sp => sp.GetService<TContext>());
services.TryAddScoped(typeof(IRepository<>), typeof(Repository<>));
return services;
}
Of course, this changes how your Repository implementation works, but I don’t actually assume that you need to know the TContext type other than to inject the database context type. So this will probably still work for you.
That being said, I have too agree with Chris Pratt, that you probably don’t need this. You say that you want to introduce the repository, because “coding stores and implementations for every entity is a time consuming task” but you should really think about whether you actually need that. A generic repository is very limited in what it can do, and mostly means that you are doing just CRUD operations. But exactly that is what DbContext and DbSet<T> already do:
C: DbContext.Add, DbSet<T>.Add
R: DbContext.Find, DbSet<T>.Find
U: DbContext.Update, DbSet<T>.Update
D: DbContext.Remove, DbSet<T>.Remove
In addition, DbContext is a “unit of work” and DbSet<T> is an IQueryable<T> which gives you a lot more control and power than a generic repository could possible give you.
You cannot have a partially open generic reference. It's all or nothing. In other words, you can try:
services.TryAddScoped(
typeof(IRepository<>),
typeof(Repository<,>));
But, if that doesn't work, you'll likely need to add a type param to your AddRepository method:
public static IServiceCollection AddRepository<TEntity, TContext>(this IServiceCollection services)
where TEntity : class
where TContext : DbContext
{
services.TryAddScoped(
typeof(IRepository<TEntity>),
typeof(Repository<TEntity, TContext>));
return services;
}
Of course, I think that breaks what you're ultimately trying to achieve here: registering repositories for all the entity types in one go. You can always use a bit of reflection find all entities in your assembly (they would need to share something in common: base class, interface, etc.) and then enumerate over them and use reflection to call AddScoped on your service collection for each.
All that said, the best thing you can do here is to actually throw all this away. You don't need the repositories. EF already implements the repository and unit of work patterns. When you use an ORM like EF, you're essentially making that your data layer instead of a custom class library you create. Putting you own custom wrapper around EF not only adds entropy to your code (more to maintain, more to test, and more than can break), but it can also mess up the way EF works in many cases, leading to less efficiency in the best cases and outright introducing bugs into your application in the worst cases.

UnitOfWork with NInject design issues

I have my UnitOfWork class in DataAccess project and to resolve my IUnitOfWork interface (with UnitOfWork class), I need to use Ninject to Bind the IUnitOfWork interface with UnitOfWork class in my web project.
To do this I need to refer my DataAccess project (which contains UnitOfWork class) in the Web project. Is this good design wise? I mean referring DataAccess in the web project seems to be a bad idea & I never did that.
So, please advise me on what to do?
If you are not comfortable having reference to DataAccess project (imho it is not a big issue) you can create separate project (let's call it ModuleProject) that will contain NinjectModules. ModuleProject will have references to both DataAccess and to project where IUnitOfWork is defined. In your web project you will have reference to ModuleProject and use its classes to register modules.
Module
public class NinjectConfiguration : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>();
}
}
Registration in web project
kernel.Load(new Mod.NinjectConfiguration());
More information on modules here.

NHibernate and IoC IInterceptor

I have been trying to implement a solution similar to what Ayende posts in his MSDN article, Building a Desktop To-Do Application with NHibernate. Fortunately, Skooletz wrote a similar article that follows up what I am trying to accomplish with his 3 part blog post on NHibernate interceptor magic tricks (1, 2, 3). I am having trouble getting my POCO object's parametered constructor to be called by NHibernate when instantiating the object.
When I remove the protected parameterless constructor, NHibernate complains with an InvalidProxyTypeException: "The following types may not be used as proxies:
YourNamespace.YourClass: type should have a visible (public or protected) no-argument constructor". If I then add in the protected default constructor, NHibernate no longer complains, but the dependency (in the overloaded constructor) is never called causing the application to barf with a NullReferenceException at runtime when the dependency is not satisfied.
public MyClass
{
IRequiredDependency dependency;
public MyClass(IRequiredDependency dependency)
{
this.dependency = dependency;
}
protected MyClass() {}
}
I just can't seem to get NHibernate to call the overloaded constructor. Any thoughts?
In the configuration of the IoC container, you have to declare your type with the dependency in addition to the dependency itself.
container.RegisterType<IRequiredDependency, RequiredDependency>();
container.RegisterType<MyClass, MyClass>();
I missed that little tidbit from Pablo's post (where he registers the Invoice class in addition to its dependency, IInvoiceTotalCalculator) as I am using Unity instead of Windsor.
One additional note: I found is that if you would like to have any other overloaded constructors, make them internal, leave the default constructor as protected and have only a single public constructor that contains your dependencies. This tidbit helped tighten up some of my API design for the classes.

Executing order of constructor injection and property injection using ninject 2

I'm loading a ninject module in my (WCF) project and want to hook up log4net in my module using a custom provider. The reason I'm using a provider is that the GetLogger method needs to get passed the class in which the Injection is taking place. If this is not the way to do this, please let me know, I'm new to Ninject. (Context.getType() is not correct btw, I'm having some trouble doing this.)
The main problem is that my ILog variables in my classes get Initialized after the constructor has executed, but I want to be able to use the logging in my constructor. I am also using Ninject to call my constructor and bind it's parameters to concrete classes.
Bind<IBroker>().To<Broker>(); // constructor
Bind<ILog>().ToProvider(new log4netILogProvider()) // property
private class log4netILogProvider : Ninject.Activation.Provider<ILog>
{
protected override ILog CreateInstance(IContext context)
{
return LogManager.GetLogger(context.getType());
}
}
All help is appreciated.
No IoC framework will ever be able to do property injection before constructor injection. An IoC framework can only do the same things you can do in a manually written factory. You can't access a property of an object in a factory before it has been created right? So can't the IoC framework.
Basically you have two options.
Do constructor injection (prefered)
Do method injection and execute your constructor code in the method.
[Inject]
public void Initialize(ILog log) { ... }
I would also suggest a third option. You can implement Ninject's IInitializable interface then see if you can't move the code that relies on the property injecttor into your implementation of Initialize(). Ninject guarantess that all constructor injection AND propery injection is finished before Initialize is invoked.

Constructor dependency injection with NHibernate 2.1 and StructureMap

I've read somewhere that NHibernate 2.1 supports constructor dependency injection for it's entites.
How do I go about configuring StructureMap and NHibnerate 2.1 to get this up and running ?
I realize this is an old question, but in case it might be useful.
EDIT: Original posted links weren't effective for NHib 2.1, found better info.
For NHibernate 2.1, you can create an Interceptor and override the Instantiate method and have your container create your instances there. Here is an example
If you wanted to do property injection instead, you can use the same technique but do your work in the onLoad method instead.
By setting up StructureMap across all of your entities (classes etc) and then using the interface for each of those as the signature for the constructor of a class...when you instantiate the class that has a dependency in its constructor StructureMap will auto inject it for you!
[PluginFamily("Default")]
public interface IWidget1
[Pluggable("Default")]
public class Widget1 : IWidget1
[PluginFamily("Default")]
public interface IAnotherWidget
[Pluggable("Default")]
public class AnotherWidget : IAnotherWidget
{
public AnotherWidget(IWidget widget)
{
...
}
}
IAnotherWidget _anotherWidget = ObjectFactory.GetInstance<IAnotherWidget>();
Something like that!
This may be of use too: Can I replace the call to Activator.CreateInstance() in NHibernate?
And this: http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspx