Tell me, is it normal practice to produce using contexts when working with the Enitity Framework or is it more correct to pass entity objects into methods as arguments?

This is what I mean by "Creating Contexts":

DoWork() { using (var db = new Entity()) { // какая-то работа с сущностью ... DoWork2(); ... // какая-то работа с сущностью } } DoWork2() { using (var db = new Entity()) { // какая-то работа с сущностью ... } } 
  • it is better to find out what the “repository” pattern is and think over the competent application architecture. - gromanev
  • 3
    @gromanev: The repository and EF are somehow not very compatible, in my opinion. - VladD
  • @VladD I didn’t work with EF - tell me why they don’t combine (you can chat). - andreycha
  • @andreycha: We had a discussion about this here somewhere, now I'll try to find it. - VladD
  • @VlaD well then tell nopCommerce developers about this;) - gromanev

3 answers 3

For many who use EF, the question arises how often we should create a DbContext , how to determine the optimal lifetime of the context.
Possible options for the lifetime of the context:

  • Function
  • The form
  • Flow
  • application

To make the right choice, I propose to consider several aspects:

  1. Correct context destruction (call to context's Dispose() method)
    Calling Dispose is an important step when working with the DbContext class. Using the using construct, we guarantee the timely call of the Dispose method and thus the release of unmanaged resources.

     using (MyContext ctx = new MyContext()) { … } 

    If you forget to call Dispose , this can lead to the leakage of open connections to the database and to the non-release of unmanaged resources.
    do-i-have-to-call-dispose-on-dbcontext

  2. The cost of the operation to create a new context class
    The operation to create a new context is inexpensive because it is basically copying metadata links from the global cache. Therefore, there is no need to worry about the cost of this operation.

  3. Memory usage
    The longer you use a DbContext object, the more memory it takes. Because it will contain all the entities (entities) that it knows about, which were requested through the queries, were added or attached. Therefore, keeping the context for a long time is not recommended.

  4. Thread safety
    The DbContext class DbContext not thread safe. If we use a context from several threads, then we ourselves must ensure synchronization of access to the context.
  5. Synchronize data with the database
    After creating the context, if you do not take additional measures, the context does not see the changed data in the database, which were made from the outside. Creating a new context, measures to synchronize data from the database do not need to be taken.

Here are the main aspects that came to mind. Therefore, contexts with a short lifetime when working with EF are normal practice and are often used when working with EF.

  • Great answer. Were there more like this ... - Walter Nuss
  • @WalterNuss here only he does not answer the question of the topicaster. Contexts are cheap (ok), they should not be held longer than necessary (ok). The question is - there are two methods that work with an entity (with the same one, apparently) in the framework of one operation (one in the middle of the other). Where is the answer in the post above — is it worth creating another context in this particular case, or not? - PashaPash
  • @PashaPash, I have listed aspects that can guide the choice of living context. I did not consider this particular case (which the author cited), but the general case of using contexts, which is easily projected onto the choice of the life context for these two functions. In your answer, I also do not agree with certain arguments, such as binding to the business process (this is not enough in most cases). Therefore, thank you for your opinion, but I think it will be politically incorrect to discuss with us which answer is better and which is worse. I think the author will be useful both answers. - Alexcei Shmakov

Context in EF is, in essence, a ready implementation of several patterns at once:

The last two significantly limit the possible options for the lifetime of the context:

Unit of work

The concept of concurrency problems.

Identity map

It keeps track of all the single business transaction . Whenever you want it, you can’t.

From the two quotes above it follows directly that the context should live exactly one business transaction:

  • If he lives less (“produce contexts” in the question) - then part of the operation code will not see the changes made before it.
  • If he lives longer, for several operations - then other operations will see irrelevant data (due to the Identity Map) or vice versa, we will see changes that have not yet been saved.

What is a business transaction (business transaction) - depends on the specific subject area. This is not a transaction in terms of databases, but a broader concept - a kind of holistic action in terms of the subject area.

Usually it is a call to the service / facade code in BL - DoWork , where Work is some kind of integral operation, action. Those. this is usually the top level function call in your application.


Considerations of memory usage, thread safety, cost of creation, synchronization with the database are completely secondary, and should not be the basis for choosing the context lifetime.

Context is an attempt to reflect in the code a complete operation from the subject area. It doesn’t matter to the domain whether you do it in one thread or in different ones, spend a lot of memory or a little, do you have to write huge methods, or manage a couple of lines - this doesn’t affect the integrity of the operation. Accordingly, the choice of the lifetime of the context should not affect.

The choice of the container in the code within which the contextt lives - the function, the form, the flow, the query, the application - is also secondary. It should be the effect, not the cause, of the lifetime of the context.

  • If a particular function ( DoWork ) corresponds to a business transaction, it must control the lifetime of the context. If not ( DoWork2 ) - then no.
  • If a business operation is stretched to the time the form is displayed, then the lifetime of the context must coincide with the form, and the context may well be the field of the form. If not, then no.
  • If you run a background operation in a separate thread, then the lifetime will most likely coincide with the lifetime of the stream. But not because it is a background operation, but because it is a background operation .
  • If you have a console application that performs exactly one business operation, then it is reasonable to use one context per application.
  • one
    <If he lives longer, for several operations, then other operations will see irrelevant data (due to the Identity Map) or vice versa, we will see changes that have not yet been saved.> I’ll correct: if these other operations will work with in the same context, they will work with actual data, not even formally laid out yet in the database. When you first save the context - all changes will be saved. Just in the presence of such an interoperable context - no need to open new ones (for the same data) - ale
  • one
    @ale yes, but changes that have not yet been saved may never be saved - for example, because of the failure of the optimistic concurrency check, or because the code in the business logic changed its mind to save them. I just could not think of an analogue of the word “actual” for data that already exists, but has not become “relevant” yet. In any case, doing an interoperable context is the same as working with the base in read uncommitted. Given the price of creating a context, it is not worth it. - PashaPash
  • PashaPash ♦, do you really think that the context in EF is a ready implementation of all these patterns? - Sergey Ignakhin
  • @ Sergey Ignakhin yes. choose any of them - and I will tell you in detail exactly how it manifests itself in EF. With links to Fowler. - PashaPash
  • @ PashaPash ♦, some manifestations do not suggest that it implements them. These are just similar moments. Otherwise, there would be no point in implementing the patterns separately) - Sergey Ignakhin

Well, on the other hand: If loading of some objects from the database and changing them while saving occurs in different places of the application and also at the initiative of the user, i.e. can be significantly separated in time - then you have to load the necessary objects again each time you create a context, for example, using the Find method with the previously saved key and working with the updated objects already. If the context is kept open, then this is not required. Only it will be necessary to work on the guaranteed closure of this long-lived context as soon as it is no longer necessary. Probably a compromise is needed here - there may be a cache with context unloading (contexts) in time, although this is no simpler than multiple loading of objects, but more productive.