I'm starting a new .NET MVC project with Entity Framework and I am struggling with some problems.
In my model I have about 150 entities (generated from the database). Is it a good idea to have only one DbContext? If not, how should I divide my entities?
If I have one DbContext and I create a class variable that instantiates a database context object (in Controller), what happens then with this DbContext? Does it create in memory separate space for each of my entities? In my case, when I have 150 entities it would not be very effective. Am I wrong?
I will be using my DbContext in many Controllers. Is it a good idea to create a MainController (where I create new DbContext), which will be inherited by the rest of the Controllers? Because this allows others to have access to the same Context.
What is the best practise for disposing my DbContext? I've read that it is good practice to use dependency injection. But in this way I will have to inject context to every of my controllers. Which dependency injection way is the most popular and used now?
Really need your advice. It will give me more insight to this piece of development.
It is fine to have one DbContext. If you have many you just need to ensure all the entities you need exist in the that context. For example, if you retrieve a Person from the database and their related Address, then both the Person and Address have to exist in the same DbContext.
I've not tried using multiple DbContext instances, but one thing to look out for is if you include the same table in multiple contexts you could end up with classes with similar names or maybe conflicts. For example, if you include Person in two contexts, then each context will attempt to create a class named Person.
When you create a DbContext it will only create objects for the data you retrieve from the database. So if you request one row from a Person table, then only one Person object will be created. If you request 100 rows, then 100 instances will be created.
There are really two options. One, create a new instance in each action, do your work, then save it. Or, create a DbContext in your constructor and reuse that throughout the class.
This depends one what you choose in point #3. If you pass it into the constructor, then implement IDisposable and release it in there. If you create a new one in each action, then ensure it gets disposed using the using statement.
For dependency injection there are a number of options, tutorials, etc, on how to do this in ASP.NET MVC. I personally use Autofac, and related MVC extensions, and pass a new instance of the DbContext into each controller.
150 Entities is not a huge DbContext, but it is above the size where EF starts to exhibit performance issues in the initialization of the first DbContext. If you can logically separate your entities into areas of responsibility (called a bounded context) then you might consider using more than one DbContext. Also, does your app need to use all those entities? If not, you may be able to simplify things. Also note, you need at least EF6 to make this work effectively, previous versions of Entity Framework had issues with multiple contexts.
You also have to be careful when using multiple contexts. Many people get into trouble because they get an entity from one context, but then call save changes on a different one, and then don't understand why their changes are not saved. Or, they try to add an entity retrieved from one to another, which you can't do. Multiple contexts make things more complicated, so make sure you want to take on that complexity before you split it up.
Don't worry about the amount of memory your DbContext uses, so long as you are properly disposing of it. The amount of memory will be minimal unless you actually load objects from all of those tables.
I consider a common base controller to be a code smell. It's usually completely unnecessary, and it usually ends up becoming a dumping ground for every piece of code you think you want to share, which violates the Single Responsibility Principal. On top of that, you shouldn't be doing data access in your controllers anyways. You should have a service layer of some sort or business layer that call into a data access layer. Properly segregating your concerns is a key part of designing a good MVC application.
Yes, Dependency Injection is a good practice. I'm not sure what you mean by "have to inject into all my controllers". The whole point of dependency injection is to inject your dependencies, so the concept of "having to" makes it seem like you're trying to avoid the very thing you're trying to do.
Dependency Injection is a principle. There are many ways to achieve this principle, and which way you use depends entirely on your own preferences and requirements. We can't tell you what's "best" other than to make sure you're following the principle, and not a specific technology.
Regarding the dbcontext question:
I would go with multiple dbcontext (bounded contexts).
One problem with single big dbcontext is the loading and the Initializing time as it will map all the entities and this increases when your entities number increase in your context.
Now your project must consist of modules and this where you can divide your big dbcontext into small db contexts that covers all what each individual module needs to work with the database, for example let's say that your project has two modules (membership and billing or financial) for customer/person entity, you will find that when you deal with person in the membership module you need all his details but not full details of his invoices, and when you deal with the person in the billing module you will need all his invoices deatils but not his full personal information, here you can create 2 dbcontexts one for each module with person entity contains what that module needs from the person entity.
Julie lerman has a good article about dbcontext with Entity-framework that start with to get more details about what I am trying to describe here,
https://msdn.microsoft.com/en-us/magazine/jj883952.aspx
Hope this helps
Ok, rookie question. I have a set of service classes the get a dbcontext passed to them in the constructor. I'm using ninject to handle this:
kernel.Bind<DbContext>().ToSelf().InRequestScope();
However I'm getting the error: "The operation cannot be completed because the DbContext has been disposed." When querying to context.
If I just create a new instance of the context in the constructor instead of passing it in everything works. Is there anything wrong with doing this in a MVC asp.net application?
The problem ended up being that I was registering one of my services in InSingletonScope. Stupid mistake and really hard to track down.
I want to save a file-system structure in a Application Scoped Bean, because this is valid for all clients.
Each client is allowed to read this bean.
But the data has to be refreshed 4 times a day, because the filesystem may be changed.
Is it possible to use a application scoped bean for this use case or are there problems with thread safety when refreshing the data?
What is the alternative way? Singleton?
All that the JSF or CDI scoped annotations will do for you is control the lifecycle of the object. Namely, when it is first referenced, the bean will be instantiated, and execute any injections or postconstruct method. In the case of ApplicationScoped it will also ensure that only one copy of the object will be produced (Unless of course you explicitly create one).
So with that being said, there is nothing different about an instance of your class versus one that is not container-managed as it relates to thread-safety. So if you change the attributes of the object while some other thread is assuming them to be consistent, you will have an issue. IMO it's an issue of synchronized access. Any operations that need to be atomic and have a consistent view of the object should take out some form of exclusive lock.
Some support from the JavaBeans spec -
2.8 Multi-Threading
Java Beans should assume that they are running in a multi-threaded environment and that several different threads may be simultaneously delivering events and/or calling methods and/or
setting properties.
It is the responsibility of each java bean developer to make sure that their bean behaves properly under multi-threaded access. For simple beans this can generally be handled by simply
making all the methods “synchronized”
We're using code first with EF5 in an MVC application.
The model was created (for reasons I won't go into) in a test harness. Then, when I try to access the dbcontext in the web app I get an invalidoperationexception stating that the model backing the context has changed.
There is no schema difference at all. In fact, I've created the database from both within the test harness & within the web app. When it's created within the web app it's fine, when it's created in another program and accessed in the web app it fails.
I notice that there is a binary representation of the model in the _MigrationHistory. I've compared this for both database creation methods and it's always the same.
What exactly does EF check to determine that the model has changed because as far as I can see everything is identical & should work either way but it doesn't which leads me to think that I'm missing something here.
I am implementing a custom ASP.NET membership provider that operates based on the custom repository class that in turn uses an Entity Framework DbContext as a mean of accessing a data.
Since this is an ASP.NET MVC application, IoC container (Ninject) is set to resolve instances of my DbContext InRequestScope.
My user data tables are a part of the single main DbContext.
Repository class is also bound to instantiate in InRequestScope. But the repository class is created by to satisfy the need of the custom MembershipProvider, which can't be set to instantiate InRequestScope. As a result, whenever I am trying to access Role data via repository, I get DbContext is already disposed exception.
Has anyone set up a similar configuration and if so, what was implemented differently to overcome the problem I am having. Thanks.
A workaround that has allowed me to continue with the project development was to manually create an instance of DbContext in Membership Provider constructor, in contrast to have Ninject inject it.
Maybe someone eventually will come up with a better approach to this particular problem, please post it here and I will remark it as an answer instead of this workaround.