20
votes
\$\begingroup\$

I am trying to use Entity Framework as simple as posible. Use UnitOfWork and Repository patterns seems to be overkill because whole web application will be pretty straightforward. I came with this idea:

public class Entity
{
    ...
}

public class MyContext : DbContext
{
    //Set database connection details here.

    public DbSet<Entity> Entities{ get; set; }
}

Register DBContext with my implementation:

public class PersistenceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<DbContext>()
                                    .ImplementedBy<MyContext>()
                                    .LifestylePerWebRequest()
                          );
    }
}

And finally I am using DBContext in controller this way:

public class HomeController : Controller
{
    private DbContext db;

    public HomeController(DbContext db)
    {
        this.db = db;
    }

    public ActionResult Index()
    {
        var entity = new Entity
        {
            //Set properties here.
        };

        db.Set<Entity>().Add(entity);
        db.SaveChanges();

        return View();
    }
}

Is this correct approach? Could there be any memory leaks or potential DBContext lifetime management problems? Could there be any problem with too many database connections opened?

I would say that this could be correct. From my quick testing it looks like it is working even when I need to use DBContext in component which is then used in controller. So DBContext instance will be shared for everything per one request. Which is the way how it should be used, I guess.

\$\endgroup\$
1
  • \$\begingroup\$ IMO you should'nt depend on DbContext. DbContext is plumbing to supply your own MyContext with underlying functionality. It's not an interface to use throughout your code. \$\endgroup\$
    – rmac
    Commented Jan 7, 2013 at 12:11

1 Answer 1

20
votes
\$\begingroup\$

You're doing it right - per-request lifestyle is exactly what you need, and you got it; this ensures your favorite IoC container disposes your context at the end of each request, and serves a new instance at each new one.

One thing bothers me though, and it's not about your code:

Use UnitOfWork and Repository patterns seems to be overkill because whole web application will be pretty straightforward.

You're using Entity Framework. DbContext, with its DbSet<T>'s, is a unit-of-work/repository pattern implementation. Some will argue it's done wrong and it's their right to be religious about a design pattern. The point is that if you use it correctly, a DbContext is a perfectly acceptable unit of work, especially if you're looking to get the damn thing done and in-line with KISS. Just make sure you call SaveChanges() as little as possible - once per request, i.e. once per instance.

If you're worried about db connections, open up your favorite SQL profiler against your database server instance, and see for yourself!

Bottomline, a DbContext is an abstraction layer over lots, lots of plumbing already. Abstracting it is often over-the-top, unless you wish to decouple your data layer from the rest of your app (say, swap EF for NHibernate).

\$\endgroup\$
4
  • \$\begingroup\$ I love the bit about UoW and repositories - helped me to justify not using a pointless abstraction in a simple CRUD app when DbContext already does most of what you need! \$\endgroup\$
    – Rowan
    Commented Jun 18, 2015 at 0:48
  • \$\begingroup\$ Old answer, hope you see this and can answer. I'm curious if your advice to call SaveChanges as little as possible is a recommended best practice, and if so could you find a/some links explaining why? My googling has turned up nothing, but a team member is really insisting this is best practice. Also, this best practice has to be weighed when you're using transactions (may need to read something you've updated before you commit). Also also, I'm only concerned about EF6 and onwards, just for context (e.g. this may have changed with EF6). Thanks! \$\endgroup\$
    – ChrisN
    Commented Oct 5, 2015 at 19:55
  • 1
    \$\begingroup\$ here is my 2c. My understanding of UoW is that an entire web request is considered a single unit, i.e. everything must succeed and be saved OR nothing must be saved (i.e. rolled back). In the case were 1 web request results in multiple calls to the db, calling SaveChanges once will be ideal, so that if a failure occurs, all queries will be rolled back. If you have multiple 'SaveChanges', you could end up with a scenario where half the queries are committed to the database, and the other half are rolled back (this is undesirable IMO).i cannot find any implementation with a single SaveChanges \$\endgroup\$
    – sawe
    Commented Nov 1, 2015 at 16:16
  • \$\begingroup\$ We have an application where we need to perform multiple saves and use the data further downstream. But we also need it to be transactional. You can achieve that by wrapping multiple context instantiations and SaveChanges() in a TransactionScope (with a using statement) \$\endgroup\$
    – user92577
    Commented Dec 17, 2015 at 21:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.