0

How do I get the most out of my Entity Framework (v4.0 or better) in my ASP MVC3 web application? My main problem is due to the request-response nature of the web, it seems I have to manually track objects being displayed on a form to the DB in order to do CUD operations. Eg. as suggested in Editing and Updating Entity Framework entity in ASP .NET MVC this seems awfully manual. Is there a way to keep my context in my session some how such that EF is doing all the work for me?

Community
  • 1
  • 1
Carlo V. Dango
  • 11,816
  • 15
  • 63
  • 107

1 Answers1

2

Don't store ObjectContext in session. Use a new context for each request processing. Here you can read something about long living contexts. If you use long living context stored in session you will have a big problem to load fresh data. Also if your user opens your application in multiple browser tabs (= same session) you can get some very unexpected results.

If you want to update just scalar values (no changes in navigation properites) you can use:

Insert scenario:

[HttpPost]
public ActionResult Insert(MyEntity entity)
{
    using (var context = new MyContext())
    {
        context.MyEntities.AddObject(entity);
        context.SaveChanges(); 
    }

    ...
}

Update scenario with fully detached object:

[HttpPost]
public ActionResult Update(MyEntity entity)
{
    using (var context = new MyContext())
    {
        context.MyEntities.Attach(entity);
        context.ObjectStateManager.ChangeObjecState(entity, EntityState.Modified);
        context.SaveChanges(); 
    }

    ...
}

Update scenario with loading object first from DB:

[HttpPost]
public ActionResult Update(MyEntity entity)
{
    using (var context = new MyContext())
    {
        int id = entity.Id;
        context.MyEntities.Single(e => e.Id == id); // You must load the record first
        context.MyEntities.ApplyCurrentValues(entity);
        context.SaveChanges(); 
    }

    ...
}

Delete scenario:

[HttpPost]
public ActionResult Delete(int id)
{
    using (var context = new MyContext())
    {
        var entity = context.MyEntities.Single(e => e.Id == id);
        context.MyEntities.DeleteObject(entity);
        context.SaveChanges(); 
    }

    ...
}

It is possible to delete the entity without loading it first but if the entity has any relation it couses a lot of troubles.

If you want to modify relations as well it can involve using either UpdateMode / TryUpdateModel as discussed here or tracking changes manually as described here. Simple relation updates on Foreign key association (the description is the same even if you don't use code-first) can be still handled by previous examples.

Community
  • 1
  • 1
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
  • How do I choose between using "Update scenario with fully detached object" and "Update scenario with loading object first from DB"? It seems all I have to do is to have a IsNew flag on my objects to determine if I should use .Add() or ApplyCurrentValues() to each object – Carlo V. Dango Apr 07 '11 at 21:27
  • 2
    It depends on your preference. The scenario with loading object form DB has additional roundtrip to database but it works in every case. Detached scenario can have serious problems when modifying object and indepenedent association. – Ladislav Mrnka Apr 07 '11 at 21:29
  • 1
    In EF4 it is better to use find() instead of single or first to load the current entity (basically find() = tryupdatemodel) – ashraf Apr 07 '11 at 21:34
  • 2
    @ashraf: As I know `Find` is available only in DbContext API = EF 4.1. The same method exists in EFv4 and is called `GetObjectByKey` but you must pass entity key as parameter which is not as easy with POCOs. Here is some example: http://stackoverflow.com/questions/5273416/entity-framework-simple-generic-getbyid-but-has-differents-pk-name/5278684#5278684 – Ladislav Mrnka Apr 07 '11 at 21:38