Maleks
Maleks

Reputation: 347

Ripe for refactoring - .NET dependency injection

As with most people I've been coming to grips with certain ins and outs of the Entity Framework. One of those things is the lifetime of the context. I'm using a repositories and have decided that a context will live for the length of the request. So the context would need to be injected from the web tier wherever that repository gets used.

I've written some code which I'm sure could be refactored (in fact, definitely!). So based on the concept above, how would you optimise the following repository helper?

public class RepositoryHelper
{

    public static CountryRepository GetCountryRepository() {
        return new CountryRepository(HttpContext.Current.GetObjectContext());
    }

    public static CurrencyRepository GetCurrencyRepository()
    {
        return new CurrencyRepository(HttpContext.Current.GetObjectContext());
    }

    public static SettingRepository GetSettingRepository()
    {
        return new SettingRepository(HttpContext.Current.GetObjectContext());
    }

}

A repository is pretty simple and would look like

public class CountryRepository
{

    private Context _context = null;
    public CountryRepository(Context context)
    {
        _context = context;
    }

    public Country GetById(int id) 
    {
        // Would return a country
    }

    public IEnumerable<Country> All()
    {
        // Would return a list of countries
    }

}

Upvotes: 3

Views: 343

Answers (4)

Lazarus
Lazarus

Reputation: 43114

The challenge here is that what you've constructed isn't a repository in the sense of the repository pattern. A objective of the repository pattern is to abstract the implementation of the data access layer from the problem domain. It's done through a repository that behaves like an in-memory collection of domain objects with which you can perform the normal CRUD functions and often a few more specific operations, i.e. GetByID(id).

The repository then hides the actual persistence layer from the application in effect allowing you to change that layer without impacting the application, i.e. you might start by storing data in a flat file and later move to an RDBMS.

You would normally create an interface to describe the methods your repository needs to implement and actually pass the repository instance around using that interface as the type. This is the abstraction, the interface is common across all possible concrete implementations of your repository but your application is oblivious (to an extent) of which is actually being used.

I'd suggest a step back, look again at the repository pattern and see if you need it. Make sure you aren't just implementing it for the sake of it and that you aren't increasing the complexity of your application unnecessarily. Once you've settled on your data access approach then you can look at how you best utilise the EF Context(s) that you have.

Upvotes: 2

jgauffin
jgauffin

Reputation: 101194

Read my answer here about how to make a generic session manager.

Then create a EntityFramework session manager (which stores the objectcontext).

Some half-done pseudo code:

public static class EntityFrameworkSession
{
    [ThreadStatic] private static ObjectContext _current;

    public static AssignToSessionFactory()
    {
         SessionFactory.Created += OnCreateObjectContext;
         SessionFactory.Disposed += OnDisposeContext;
    }

    public static void OnDisposeContext(object source, SessionEventArgs e)
    {
         if (e.Saved)
           _myContext.SaveChanges();
    }
}

And in your repositories use:

EntityFrameworkSession.Current

to access the context.

Upvotes: 0

Andrew
Andrew

Reputation: 5430

For DI you can use Ninject and use the InRequestScope method when binding objects.

Upvotes: 0

smartcaveman
smartcaveman

Reputation: 42276

I think you would benefit from using a Repository Provider class and Repository Factories like in the answer to C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories? .

Upvotes: 0

Related Questions