Entity Framework needs Session and HttpContext?

0

I watched some videos about Entity and saw two different versions, in a first it was something simple and straightforward (I believe the raw form of Entity), where it only instantiated the context of the bank and applied the add, :

using(sampleEntities ctx = new sampleEntities()){
client clt = new client();
clt.name = txtName.Text;
clt.phone = txtPhone.Text;
ctx.Add(clt);
ctx.SaveChanges();

But another teacher in another video does something different using the DAL , BLL and UI layers, this time also adding a Session that would "isolate" each operation of each user on the site, while the first version supposedly would have conflicts between the many users who would be making use of the same connection for several operations simultaneously, follow the example:

public static sample01Entities Current
{
    get
    {
           if (System.Web.HttpContext.Current.Session["SampleDbContext"] == null)
        {
            db = new sample01Entities();
            System.Web.HttpContext.Current.Session["SampleDbContext"] = db;
        }
        return db;

    }
}

And here in the DALCity class:

    public void Add(cidade c)
{
    SampleDbContext.Current.cidade.Add(c);
    SampleDbContext.Current.SaveChanges();
    SampleDbContext.Current.ChangeTracker.Entries<cidade>();
}

The question is: is it safe to use the first form for CRUD operations without compromising code / site / security etc? Or should I always use the second example with the Session to "individualize" operations and connections?

Thank you all.

    
asked by anonymous 27.01.2016 / 01:48

1 answer

1

Using the Session with the Entity Framework is, on the contrary, discouraged.

1) DbContext implements the standard Unit of Work. This means that your goal is to help you include and load your entities, modify them, and then finally send all those commands to your base. Classes that have this behavior are not meant to have a long lifecycle in this way, in which the object is created as static once and used for all other requests.

2) It is normal for sessions to be created and destroyed throughout your requests and for your application to be recycled from time to time. In both cases, using a static object with session may bring some unexpected scenarios, such as loss of information and invalid states of your Context object.

3) Even if you do not fall into a scenario like the one above, we fall into the problem of the long life cycle. The Context object caches all information that is queried / modified over time (it does not have any Garbage Collector itself), which means that you end up with several unnecessary objects and a gigantic memory potential being used unnecessarily. Considering that each user would have a different context, probably much of that memory would still have duplicate information between them. If we're talking about a Session Inproc scenario, it would be even worse, because all that allocated memory would still undermine your Web server's ability to respond to more requests.

4) DbContext is not Thread-safe. This means that it is not meant to be shared by multiple simultaneous requests because you run the risk of falling into race conditions, among other issues that may throw you into invalid states or make use of outdated or different information

Creating new instances of contexts is not such a time-consuming or expensive activity to process. In Web applications, it is common for an instance to be used per request or by specific operation.

There are a number of articles out there on the internet explaining how to use context on demand through dependency injection containers (Ninject, Unity, SimpleInjector, etc.). But if you do not want to use them, you can try to keep them inside the HttpContext object:

public static class RequestContext
{
    public static sampleEntities Current
    {
        get
        {
            if (!HttpContext.Current.Items.Contains("EFContext"))
            {
                HttpContext.Current.Items.Add("EFContext", new sampleEntities());
            }
            return HttpContext.Current.Items["EFContext"] as sampleEntities;
        }
    }
}

Global.asax:

protected void Application_EndRequest(object sender, EventArgs e)
{
     var context = HttpContext.Current.Items["EFContext"] as sampleEntities;
     if (context != null)
         context.Dispose();
}

Your usage example:

public void Add(cidade c)
{
    var context = RequestContext.Current;

    context.cidade.Add(c);
    context.SaveChanges();
    context.ChangeTracker.Entries<cidade>();
}

I think the dependency injection scenario might give you better control, but that approach works too.

Recommended reading some articles for a better understanding of how to use Entity Framework context appropriately: Managing DbContext the right way with Entity Framework 6: an in-depth guide MSDN - Working with DbContext

    
27.01.2016 / 11:13