Share datacontext / inject dependencies Entity Framework 6 Code First - entity-framework

How does one share the datacontext of Entity Framework 6.1.1. and inject dependencies (I use Ninject ) like repositories, since EF6 supports repositories and UoW out of the box?
All I can find are SO question and blogpost/articles at least 3 years old. But nothing about EF6, and the current situation which is repositories and UoW being supported out of the box.
The solution contains 2 projects, one is the web project (asp.net-mvc), the other one is the class library acting as the datalayer. The datalayer is based on Code First.
I did create repositories, but didn't realize it was already supported out of the box.
I installed ninject.mvc5 and this is what I registered:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind<IOrderRepository>().To<OrderRepository>().InRequestScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
}
So I guess I need to re-factor my code and remove the repositories. But I don't know what should replace them?

Repositories are your DbSets inside the DbContext. The DbContext is your UoW.
Whenever the UoW was used before, you use DbContext now. And you no longer pass individual repositories around, you pass the whole DbContext (it was, frankly, unusual habit before to pass individual repositories, although many people did that).
This now is sufficient then
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
The ApplicationDbContext is then injected via constructor injection to upper layer classes where applicable.

Related

DbContextScope Pattern for EF Core 3

Some of you may be familiar with the DbContextScope library, which allows you to nest scopes within your code, and allow those scopes to share a common DbContext. The idea is that the DbContext gets managed for you by the scope library, and instead of calling SaveChanges() on the context, you call SaveChanges() on the scope. The magic happens because the scope will only save all the changes on the context at it's outer-most call of SaveChanges(), so all the nested operations performed on the DbContext get saved in a single transaction at the outer scope-level.
Now that DI is a first-class citizen in .NET Core, it appears that scopes have also become an important part of the .NET Core ecosystem, and the EF Core team, knowing this, has implemented scoping based on allowing DbContexts being injected by the DI system, and (I assume) allowing change saving to happen at scope-levels and not directly on the DbContexts in some way.
So my question are these:
What is the appropriate way to share a DbContext via a scope, allowing the SaveChanges() be managed at the scope level and not the code-level that typically calls SaveChanges() on the DbContext?
Are there new mechanisms in EF Core that manage this for you, just like DbContextScope did this for you as a 3rd party library?
Save me the drama, and spare me the lectures on why you think UOW needs to be implemented in addition to EF. K thnxs bye.
UPDATE: As of 6/2020 there are several forks of DbContextScope that work with EF Core 3.
UPDATE: Forks of this project can be viewed here: https://github.com/mehdime/DbContextScope/network
There are several EF Core 3 versions... I haven't tried any yet, but there you go.
Since Entity Framework 5.0.0, there is IDbContextFactory<TDbContext> that lets you control the creation and disposal (!!) of your DbContexts.
Instead of registering your DbContext with AddDbContext or AddDbContextPool, you can now use AddDbContextFactory or AddPooledDbContextFactory, respectively.
Note that this feature takes care of one of the problems that DbContextScope solves, not all of them. As for what the other problems and solutions are, refer to Mehdi's original post. It is long but excellent.
DbContext sharing is built-in to the Dependency Injection design for EF.
The DI container will generate a scoped DbContext instance for each web request. You can share the DbContext instance from any component that has a dependency on it, and call SaveChanges(), or manage transactions in your outer controller.

Entity Framework 4 with Generic Repository

i developed an sample application using Entity Framework 4.0. but now i'm gonne developed a real app for a company. where i would like to implement the DAL with Entity framework with generic repository , unit of work and DI container.
please any one suggest me a real example for the framework..
Thanks
Rusho
Generic repository is nonsense. If you want to use design pattern called Repository you should think about specific repository and aggregate roots.
Generic repository is just a wrapper around ObjectSet / DbSet providing no added value - only additional layer which must be maintained and which makes interaction with EF harder. Also adding repository without clarifying why you want to do that and what it should solve for you is wrong approach - design pattern is a blue print for solving a problem. Not something you should use just because it exists and everybody talks about it.
You can also check these answers where I discuss generic repository and its implications:
Generic Repository With EF 4.1 what is the point
The repository itself is not usually tested?

Access DbContext from IQueryable

I am trying to implement a caching pattern which may need to utilise Redis. The problem with this pattern is that I need to disable Configuration.ProxyCreationEnabled and then re-enable it afterwards to avoid any issues across a web farm.
What I would like to do is access the DbContext from the IQueryable so I can do this once instead of everywhere. The easiest way to do this is to pass the DbContext being used into my caching extension, however I came across this post:
Access DataContext behind IQueryable
Is there a way of accessing the DbContext in a similar manner to the link above using EF 4.1 Code Fist (DbSet's, etc)?
I have tried to find this myself but have struggled to find the base class from the referenced DbSet in the IQueryable using reflection.
The solution mentioned in Access DataContext behind IQueryable is a hack and should not be used. It relies on the name of a private member variable in the class implementing IQueryable. This means that the implementing class could change in a future release of EF/.NET Framework and break your code. Since the DbContext is not accessible through the IQueryable interface, you should pass it into your caching extension to avoid making assumptions about the IQueryable implementation. Doing so will also more clearly establish the dependency on the DbContext in your caching interface, instead of burying it in the implementation.

Entity Framework generic repository life cycle

I've read a couple of articles about creating a generic repository in Entity Framework. In every article the ObjectContext is passed as an argument to the constructor like this:
public Repository(ObjectContext context)
{
_context = context;
}
In a web application the preferred way to handle ObjectContext lifestyle is per web request. This means that these repositories must also have lifestyle per web request, if used in in a web context. This spreads to services using repositories and further on if we stick to constructor injection...
I think the ObjectContext life cycle should be handled outside the repositories, for example in a HttpModule. I would also like to handle repositories as singletons instead, and then ObjectContext can't be injected in the constructor. Another mechanism for getting the ObjectContext into the repository must be used, like an ObjectContextFactory.
Whats the downside of handling the repositories with a singleton lifestyle?
One issue with repositories being singletons, as with any other objects, is that determining what dependencies the repository has becomes more difficult. When you require that a context is passed in the constructor that is a clear declaration of a dependency on the ObjectContext class. If you were to use a static factory to get a reference to an object context then it would be necessary to see the implementation of the repository to know how it uses the factory.
A common way to achieve what you're looking for, namely the ability to manage the scope of the ObjectContext class outside of the repository is by using a dependency injection library, such as Autofac. You can register the ObjectContext class such that a new instance is created for every HTTP request. Then if you also register the repository class, when a repository is requested the dependency injection container will attempt to get a reference to the ObjectContext dependency. Since only one instance of ObjectContext will be created per HTTP request multiple repositories within that scope will receive the same instance. The Autofac page has example of integrating with ASP.NET that you can look at.

How to provide ASP.NET MVC2 master pages with a model indepdent of the controller

I'm using strongly typed views and autofac for Dependency Injection under ASP.NET MVC2 and I'm trying to get a common dynamic header via dependency injection. I.e. i want this to happen without the view having to be away of this content even existing and i was hoping to avoid static discovery of the container and manual resolution, but I can't find a way to easily inject the master or a partial view included in the master via either ctor or property injection.
I can't imagine this is an uncommon task, but all I can find in terms of methods is Controller subclassing to stuff data into untyped ViewData, subclassing ViewModels to stuff master data into the model, or static resolution, all of which I'd prefer not to use. What am I overlooking?
EDIT: As has been pointed out DI into master pages is fighting the framework. So my question is badly framed: I don't really care about DI into master pages, but I have a dynamic element in the chrome of the site, i.e. the master page. Providing it with a model shouldn't be the responsibility of each controller using that master, as it is request context, not controller context specific. I fully admit that injection directly into master pages is inappropriate. If i could register a separate master controller to be invoked in addition, that would be even better. Is that possible? Given this task of providing the master with a model independent of the controller, what is the framework appropriate approach? Or does shared content in MVC require that each Controller has to know about that content?
You could use child actions.
Controller:
public class MyHeaderController: Controller
{
private readony IRepository _repository;
public MyHeaderController(IRepository repository)
{
_repository = repository;
}
[ChildActionOnly]
public ActionResult Index()
{
var model = _repository.GetSomeModel();
return PartialView(model);
}
}
And somewhere in your master page include it:
<div><%= Html.Action("Index", "MyHeader") %></div>
Your problems stem from confusing the term Dependency Injection, and fighting how the ASP.NET MVC framework works.
Also, you are using the term Dependency Injection in the wrong context. You are trying to use a hammer as a chisel.
MasterPages and views in ASP.NET MVC are intended to be used as templates. As stated in the other answer, child actions will solve your problem.
For future reference:
Dependency Injection refers to a means to configure what parameters to inject into class constructors, and have this done for you automatically, overriding some of the frameworks defaults. The purpose for this is to decouple components, so that they become more reusable, more testable, more unitary, amongst other good things.
DI refers to, and solves, a code issue, not a UI issue.
What you are trying to do is simply not possible. Ie, inject via constructors and properties a "dependency" into a masterpage. Again, MasterPages are intended by ASP.NET MVC to be used as just templates. They have no code behind class to instantiate via a constructor that would allow dependencies to be injected into it.
In other words, you are fighting the framework, which means you don't understand it.
If this sounds like nitpicking, I think this has to be highlighted as otherwise, you are confusing yourself and others who read this thread in the future.