Sorted By: Tag (entity-framework)

Clean, Better, and Sexier Generic Repository Implementation for Entity Framework

With the new release of the GenericRepository.EntityFramework package, we now have clean, better and sexier generic repository implementation for Entity Framework. Enjoy!
2013-01-10 13:00
Tugberk Ugurlu


I have written a few blog posts about my experience on applying the Generic Repository pattern to Entity Framework and I even made a NuGet package for my naïve implementation. Even if that looked OK at the time for me, I had troubles about my implementation for couple of reasons:

  • The implementations inside the NuGet package didn’t allow the developer to share the DbContext instance between repositories (per-request for example).
  • When the generic repository methods weren’t enough, I was creating new repository interfaces and classes based on the generic ones. This was the biggest failure for me and didn’t scale very well as you can imagine.
  • There were no pagination support.
  • As each repository take a direct dependency on DbContext and it is impossible to entirely fake the DbContext, generic repositories needed to be mocked so that we could test with them. However, it would be just very useful to pass a fake DbContext instance into the repository implementation itself and use it as fake.

With the new release of the GenericRepository.EntityFramework package, the all of the above problems have their solutions. The source code for this release is available under the master branch of the repository and you can also see the ongoing work for the final release under the v0.3.0 branch. The NuGet package is available as pre-release for now. So, you need to use the –pre switch to install it.

PM> Install-Package GenericRepository.EntityFramework -Pre

The old GenericRepository.EF package is still around and I will update it, too but it’s now unlisted and only thing it does is to install the GenericRepository.EntityFramework package.

I also included a sample application which shows the usage briefly. I will complete the sample and extend it further for a better view. Definitely check this out!

Let’s dive right in and see what is new and cool.

IEntity and IEntity<TId> Interfaces

I introduced two new interfaces: IEntity and IEntity<TId> and each of your entity classes needs to implement one of these. As you can see from the implementation, IEntity just implements the IEntity<int> and you can use IEntity if you are using integer based Ids. The reason why I added these is make the GetSingle method work.

Use EntitiesContext Instead of DbContext

Instead of deriving your context class from DbContext, you now need to take the EntitiesContext as the base class for your context. If you have an existing context class based on DbContext, changing it to use EntitiesContext should not break it. The EntitiesContext class has all the same constructors as DbContext. So, you can also use those. Here is the sample:

public class AccommodationEntities : EntitiesContext {

    // NOTE: You have the same constructors as the DbContext here. E.g:
    // public AccommodationEntities() : base("nameOrConnectionString") { }

    public IDbSet<Country> Countries { get; set; }
    public IDbSet<Resort> Resorts { get; set; }
    public IDbSet<Hotel> Hotels { get; set; }
}

Then, through your IoC container, you can register your context as a new instance for IEntitiesContext per a particular scope. The below example uses Autofac to do that for an ASP.NET Web API application:

private static void RegisterDependencies(HttpConfiguration config) {

    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register IEntitiesContext
    builder.Register(_ => new AccommodationEntities())
           .As<IEntitiesContext>().InstancePerApiRequest();

    // TODO: Register repositories here

    config.DependencyResolver = 
        new AutofacWebApiDependencyResolver(builder.Build());
}

IEntityRepository<TEntity> and EntityRepository<TEntity>

Here is the real meat of the package: IEntityRepository and EntityRepository. Same as the IEntity and IEntity<TId>, we have two different IEntityRepository generic interfaces: IEntityRepository<TEntity> and IEntityRepository<TEntity, TId>. They have their implementations under the same generic signature: EntityRepository<TEntity> and EntityRepository<TEntity, TId>. The big improvement now is that EntityRepository generic repository implementation accepts an IEntitiesContext implementation through its constructor. This, for example, enables you to use the same DbContext (IEntitiesContext implementation in our case, which is EntitiesContext by default) instance per-request for your ASP.NET MVC, ASP.NET Web API application and share that across your repositories. Note: don’t ever use singleton DbContext instance throughout your AppDomain. DbContext is not thread safe.

As we have registered our EntitiesContext instance per request above, we can now register the repositories as well. As our repositories accepts an IEntitiesContext implementation through their constructor, our IoC container will use our previous registration for that automatically. Autofac has this ability as nearly all IoC containers do.

private static void RegisterDependencies(HttpConfiguration config) {

    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register IEntitiesContext
    builder.Register(_ => new AccommodationEntities())
           .As<IEntitiesContext>().InstancePerApiRequest();

    // TODO: Register repositories here
    builder.RegisterType<EntityRepository<Country>>()
           .As<IEntityRepository<Country>>().InstancePerApiRequest();
    builder.RegisterType<EntityRepository<Resort>>()
           .As<IEntityRepository<Resort>>().InstancePerApiRequest();
    builder.RegisterType<EntityRepository<Hotel>>()
           .As<IEntityRepository<Hotel>>().InstancePerApiRequest();

    config.DependencyResolver = 
        new AutofacWebApiDependencyResolver(builder.Build());
}

Out of the Box Pagination Support

Best feature with this release is out of the box pagination support with generic repository instances. It doesn’t perform the pagination in-memory; it queries the database accordingly and gets only the parts which are needed which is the whole point Smile Here is an ASP.NET Web API controller which uses the pagination support comes with the EntityRepository:

public class CountriesController : ApiController {

    private readonly IEntityRepository<Country> _countryRepository;
    private readonly IMappingEngine _mapper;
    public CountriesController(
        IEntityRepository<Country> countryRepository, 
        IMappingEngine mapper) {

        _countryRepository = countryRepository;
        _mapper = mapper;
    }

    // GET api/countries?pageindex=1&pagesize=5
    public PaginatedDto<CountryDto> GetCountries(int pageIndex, int pageSize) {

        PaginatedList<Country> countries = 
             _countryRepository.Paginate(pageIndex, pageSize);

        PaginatedDto<CountryDto> countryPaginatedDto = 
           _mapper.Map<PaginatedList<Country>, PaginatedDto<CountryDto>>(countries);

        return countryPaginatedDto;
    }
}

public interface IPaginatedDto<out TDto> where TDto : IDto {

    int PageIndex { get; set; }
    int PageSize { get; set; }
    int TotalCount { get; set; }
    int TotalPageCount { get; set; }

    bool HasNextPage { get; set; }
    bool HasPreviousPage { get; set; }

    IEnumerable<TDto> Items { get; }
}

public class PaginatedDto<TDto> : IPaginatedDto<TDto> where TDto : IDto {

    public int PageIndex { get; set; }
    public int PageSize { get; set; }
    public int TotalCount { get; set; }
    public int TotalPageCount { get; set; }

    public bool HasNextPage { get; set; }
    public bool HasPreviousPage { get; set; }

    public IEnumerable<TDto> Items { get; set; }
}

Paginate method will return us the PaginatedList<TEntity> object back and we can project that into our own Dto object as you can see above. I used AutoMapper for that. If I send a request to this API endpoint and ask for response in JSON format, I get back the below result:

{
    "PageIndex":1,
    "PageSize":2,
    "TotalCount":6,
    "TotalPageCount":3,
    "HasNextPage":true,
    "HasPreviousPage":false,
    "Items":[
      {
        "Id":1,
        "Name":"Turkey",
        "ISOCode":"TR",
        "CreatedOn":"2013-01-08T21:12:26.5854461+02:00"
      },
      {
        "Id":2,
        "Name":"United Kingdom",
        "ISOCode":"UK",
        "CreatedOn":"2013-01-08T21:12:26.5864465+02:00"
      }
    ]
}

Isn’t this perfect Smile There are other pagination method inside the EntityRepository implementation which supports including child or parent entities and sorting. You also have the ToPaginatedList extension method and you can build your query and call ToPaginatedList on that query to get PaginatedList<TEntity> object back.

Extending the IEntityRepository<TEntity>

In my previous blog posts, I kind of sucked at extending the generic repository. So, I wanted to show here the better approach that I have been taking for a while now. This is not a feature of my generic repository, this is the feature of .NET itself: extension methods! If you need extra methods for your specific repository, you can always extend the IEntityRepository<TEntity, TId> which gives you a better way to extend your repositories. Here is an example:

public static class HotelRepositoryExtensions {

    public static IQueryable<Hotel> GetAllByResortId(
        this IEntityRepository<Hotel, int> hotelRepository, int resortId) {

        return hotelRepository.FindBy(x => x.ResortId == resortId);
    }
}

What is Next?

My first intention is finish writing all the tests for the whole project, fix bugs and inconsistencies for the v0.3.0 release. After that release, I will work on EF6 version for my generic repository implementation which will have sweet asynchronous support. I also plan to release a generic repository implementation for MongoDB.

Stay tuned, install the package, play with it and give feedback Winking smile

GenericRepository.EF Version 0.2.1 Has Been Released

Entity Framework DbContext Generic Repository Implementation v0.2.1 has been released and pushed to Nuget live feed PM> Install-Package GenericRepository.EF
2012-03-07 08:32
Tugberk Ugurlu


Couple of weeks ago, I have done two blog post on Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle and How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking and I have put up the https://github.com/tugberkugurlu/GenericRepoWebApp up on GitHub as well.

Now, the Generic Repository implementation has its own project separately: https://github.com/tugberkugurlu/GenericRepository. This is a simple project and has not much inside it but it is nice to have something static so that it can be improved along the way.

I also blogged about Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub and now I have just pushed the the version 0.2.1 to Nuget live feed.

@bmccord has done all the additions and I would like to thank him for that.

Here is a brief intro about this mini project:

This little project contains a Generic Repository infrastructure for .NET applications and also a DbContext Implementation of that.

You can find more information about the main idea of this pattern and the usage on ASP.NET MVC along with Unit Testing by visiting the below links:

How to Install

You can directly install this little project from Nuget. There are two packages:

GenericRepository

PM> Install-Package GenericRepository

Generic Repository Infrastructure For .NET Applications

GenericRepository.EF

PM> Install-Package GenericRepository.EF

Generic Repository DbContext Implementation

Releases

Under the master branch, you can find the latest stable release of this project.

Also, you can see the most up-to-date project under develop branch. Repository under develop branch is possibly the unstable version of the project.

You can also find all the releases under Tags section.

I await for your PRs :)

Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub

Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub: PM> Install-Package GenericRepository.EF
2012-01-15 08:41
Tugberk Ugurlu


Couple of weeks ago, I have done two blog post on Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle and How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking and I have put up the https://github.com/tugberkugurlu/GenericRepoWebApp up on GitHub as well.

Now, the Generic Repository implementation has its own project separately: https://github.com/tugberkugurlu/GenericRepository. This is a simple project and has not much inside it but it is nice to have something static so that it can be improved along the way.

Here is a brief intro:

This little project contains a Generic Repository infrastructure for .NET applications and also a DbContext Implementation of that.

You can find more information about the main idea of this pattern and the usage on ASP.NET MVC along with Unit Testing by visiting the below links:

How to Install

You can directly install this little project from Nuget. There are two packages:

GenericRepository

image

Generic Repository Infrastructure For .NET Applications

GenericRepository.EF

image

Generic Repository DbContext Implementation

Releases

Under the master branch, you can find the latest stable release of this project.

Also, you can see the most up-to-date project under develop branch. Repository under develop branch is possibly the unstable version of the project.

You can also find all the releases under Tags section.

I await for your PRs :)

How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking

In this blog post we will see how to work with generic repositories on ASP.NET MVC and unit testing them by mocking with moq
2011-12-22 17:05
Tugberk Ugurlu


image

I have blogged about Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle but that blog post only contains how we can implement that pattern on our DAL (Data Access Layer) project. Now, let’s see how it fits into our ASP.NET MVC application.

I created a sample project which basically has CRUD operations for Foo class and I put the complete code of the project on GitHub. https://github.com/tugberkugurlu/GenericRepoWebApp

So, in the previous blog post we have created our DAL project and repository classes based on our generic repository. I have created an ASP.NET MVC 3 Web Application project and a Visual Studio Test Project besides the DAL project. On the left had side, you can see how the project structure looks like inside solution explorer.

When we think about the project, we have repository classes which implements GenericRepositroy<C, T> abstract class and individual repository interfaces. So, we need a way to inject our concrete repository classes into our ASP.NET MVC application so that we make our application loosely coupled which means unit testing friendly.

Fortunately, ASP.NET MVC has been built with unit testing in mind so it makes dependency injection very easy with DependencyResolver class. DependencyResolver class Provides a registration point for dependency resolvers that implement IDependencyResolver or the Common Service Locator IServiceLocator interface. But we won’t be dealing with that class at all. Instead, we will use a third party dependency injector called Ninject. Ninject also has a package which benefits from DependencyResolver of ASP.NET MVC. We will use Nuget to bring down Ninject.

image

After we install the package, we will see a folder named App_Start added to our project. Inside that folder, open up the NinjectMVC3.cs file and go to RegisterServices method. In our case, here what we do:

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel) {

    kernel.Bind<IFooRepository>().To<FooRepository>();
    kernel.Bind<IBarRepository>().To<BarReposiltory>();
}

This does some stuff behind the scenes and I won’t go into details here but I really recommend you to go and take a look at series of blog posts which Brad Wilson has done on ASP.NET MVC 3 Service Location. However, if we try to explain it with simplest words, Ninject news up the controller classes with parameters which we specify. In this case, if a controller constructor accepts a parameter which is type of IFooRepository, Ninject will give it FooRepository class and news it up. We will see why this is useful on unit testing stage.

When we look inside the RegisterServices method, we don’t see neither GenericRepository nor IGenericRepository because the way we implement them enables them to work behind the scenes.

As for the implementation, here how the controller looks like:

public class FooController : Controller {

    private readonly IFooRepository _fooRepo;
    
    public FooController(IFooRepository fooRepo) {
        _fooRepo = fooRepo;
    }

    public ViewResult Index() {

        var model = _fooRepo.GetAll();
        return View(model);
    }

    public ActionResult Details(int id) {

        var model = _fooRepo.GetSingle(id);
        if (model == null)
            return HttpNotFound();

        return View(model);
    }

    public ActionResult Edit(int id) {

        var model = _fooRepo.GetSingle(id);
        if (model == null)
            return HttpNotFound();

        return View(model);
    }

    [ActionName("Edit"), HttpPost]
    public ActionResult Edit_post(Foo foo) {

        if (ModelState.IsValid) {

            try {
                _fooRepo.Edit(foo);
                _fooRepo.Save();

                return RedirectToAction("details", new { id = foo.FooId });

            } catch (Exception ex) {
                ModelState.AddModelError(string.Empty, "Something went wrong. Message: " + ex.Message);
            }
        }

        //If we come here, something went wrong. Return it back.
        return View(foo);
    }

    public ActionResult Create() {

        return View();
    }

    [ActionName("Create"), HttpPost]
    public ActionResult Create_post(Foo foo) {

        if (ModelState.IsValid) {

            try {
                _fooRepo.Add(foo);
                _fooRepo.Save();

                return RedirectToAction("details", new { id = foo.FooId });

            } catch (Exception ex) {
                ModelState.AddModelError(string.Empty, "Something went wrong. Message: " + ex.Message);
            }
        }

        //If we come here, something went wrong. Return it back.
        return View(foo);

    }

    public ActionResult Delete(int id) {

        var model = _fooRepo.GetSingle(id);
        if (model == null)
            return HttpNotFound();

        return View(model);
    }

    [ActionName("Delete"), HttpPost]
    public ActionResult Delete_post(int id) {

        var model = _fooRepo.GetSingle(id);
        if (model == null)
            return HttpNotFound();

        _fooRepo.Delete(model);
        _fooRepo.Save();

        return RedirectToAction("Index");
    }
}

All of the action methods do some very basic stuff but one thing to notice here is the below code:

    private readonly IFooRepository _fooRepo;
    
    public FooController(IFooRepository fooRepo) {
        _fooRepo = fooRepo;
    }

As I mentioned before, controller constructor accepts a parameter which is type of IFooRepository and inside the constructor method, we expose the parameter for internal use of that controller class.

I have some views which corresponds to each action method and they work as expected.

Unit Testing

So, how do we unit test that controller without connecting to our database? When we think theoretically, what we need is a fake repository which implements IFooRepository interface so that we can pass that fake repository into our controller as a constructor parameter. Pay attention here that we still has no need for neither generic repository interface nor generic repository abstract class. We just need to fake FooRepository interface with fake data.

We will do this by mocking and creating mock objects. In order to do that, we will benefit from an awesome library called Moq.

As you can see inside the project on GitHub, I didn’t use NuGet to bring down the Moq because I tried and it failed over and over again. So, I put that inside the lib folder under the root directory and reference it from there.

After you reference the Moq library inside the Test application, create a class named FooControllerTest.cs. Here how it should look like at first:

[TestClass]
public class FooControllerTest {

}

So empty. We will start to fill it in with a mock of IFooReporsitory. Below, you can see the complete code which enables that:

[TestClass]
public class FooControllerTest {

    private IFooRepository fooRepo;

    [TestInitialize]
    public void Initialize() {

        //Mock repository creation
        Mock<IFooRepository> mock = new Mock<IFooRepository>();
        mock.Setup(m => m.GetAll()).Returns(new[] { 
            new Foo { FooId = 1, FooName = "Fake Foo 1" },
            new Foo { FooId = 2, FooName = "Fake Foo 2" },
            new Foo { FooId = 3, FooName = "Fake Foo 3" },
            new Foo { FooId = 4, FooName = "Fake Foo 4" }
        }.AsQueryable());

        mock.Setup(m => 
            m.GetSingle(
                It.Is<int>(i => 
                    i == 1 || i == 2 || i == 3 || i == 4
                )
            )
        ).Returns<int>(r => new Foo { 
            FooId = r,
            FooName = string.Format("Fake Foo {0}", r)
        });

        fooRepo = mock.Object;
    }

}

This Initialize method will run before all of the test methods run so we can work inside that method in order to mock our object.

In here, first I have setup a mock for GetAll method result and it returns 4 instances or Foo class.

Second, I do the same thing for GetSingle method. It looks a little different because it accepts a parameter type of int. What I am telling there is that: there are 4 instances I have here and if the parameter matches one of those instances, it will returns a Foo class which is a type of GetSingle method returns.

Lastly, I expose the mock object for internal use for the test class.

Now we have an IFooRepository instance we can work with. We have completed the hard part and now we can start writing our unit tests. Here is some of possible unit tests that we can have:

[TestClass]
public class FooControllerTest {

    private IFooRepository fooRepo;

    [TestInitialize]
    public void Initialize() {

        //Mock repository creation
        Mock<IFooRepository> mock = new Mock<IFooRepository>();
        mock.Setup(m => m.GetAll()).Returns(new[] { 
            new Foo { FooId = 1, FooName = "Fake Foo 1" },
            new Foo { FooId = 2, FooName = "Fake Foo 2" },
            new Foo { FooId = 3, FooName = "Fake Foo 3" },
            new Foo { FooId = 4, FooName = "Fake Foo 4" }
        }.AsQueryable());

        mock.Setup(m => 
            m.GetSingle(
                It.Is<int>(i => 
                    i == 1 || i == 2 || i == 3 || i == 4
                )
            )
        ).Returns<int>(r => new Foo { 
            FooId = r,
            FooName = string.Format("Fake Foo {0}", r)
        });

        fooRepo = mock.Object;
    }

    [TestMethod]
    public void is_index_returns_model_type_of_iqueryable_foo() {
        
        //Arrange
        //Create the controller instance
        FooController fooController = new FooController(fooRepo);

        //Act
        var indexModel = fooController.Index().Model;

        //Assert
        Assert.IsInstanceOfType(indexModel, typeof(IQueryable<Foo>));
    }

    [TestMethod]
    public void is_index_returns_iqueryable_foo_count_of_4() {

        //Arrange
        //Create the controller instance
        FooController fooController = new FooController(fooRepo);

        //Act
        var indexModel = (IQueryable<object>)fooController.Index().Model;

        //Assert
        Assert.AreEqual<int>(4, indexModel.Count());
    }

    [TestMethod]
    public void is_details_returns_type_of_ViewResult() {

        //Arrange
        //Create the controller instance
        FooController fooController = new FooController(fooRepo);

        //Act
        var detailsResult = fooController.Details(1);

        //Assert
        Assert.IsInstanceOfType(detailsResult, typeof(ViewResult));
    }

    [TestMethod]
    public void is_details_returns_type_of_HttpNotFoundResult() { 

        //Arrange
        //Create the controller instance
        FooController fooController = new FooController(fooRepo);

        //Act
        var detailsResult = fooController.Details(5);

        //Assert
        Assert.IsInstanceOfType(detailsResult, typeof(HttpNotFoundResult));
    }
}

When I run the all the test, I should see all of them pass and I do:

image

I hope this blog post gives you an idea. Stay tuned for others Winking smile

NOTE:

Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub: http://www.tugberkugurlu.com/archive/entity-framework-dbcontext-generic-repository-implementation-is-now-on-nuget-and-github

Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle

We will see how we can implement Generic Repository Pattern with Entity Framework and how to benefit from that.
2011-12-22 09:07
Tugberk Ugurlu


IMPORTANT NOTE:

I have a new blog post about Generic Repository implementation for Entity Framework. Please check it out instead of this one: Clean, Better, and Sexier Generic Repository Implementation for Entity Framework

NOTE:

Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub: http://www.tugberkugurlu.com/archive/entity-framework-dbcontext-generic-repository-implementation-is-now-on-nuget-and-github

DRY: Don’t repeat yourself which is a principle of software development aimed at reducing repetition of information of all kinds, especially useful in multi-tier architectures. That’s what Wikipedia says. In my words, if you are writing the same code twice, follow these steps:

  • Step back.
  • Sit.
  • Think about it and dwell on that.

That’s what I have done for repository classes on my DAL projects. I nearly all the time use Entity Framework to reach out my database and I create repositories in order to query and manipulate data inside that database. There are some specific methods which I use for every single repository. As you can assume, those are FindBy, Add, Edit, Delete, Save. Let’s see on code what is my story here.

First approach (worst approach)

At first, long time ago, I have been creating all the single methods for each interface. For example below one is one of my repository interfaces:

I am giving the examples here with EF 4.2 but I was following this approach with EF 4 which does not contain DbContext class.

public interface IFooRepository {
        
    IQueryable<Foo> GetAll();
    Foo GetSingle(int fooId);
    IQueryable<Foo> FindBy(Expression<Func<Foo, bool>> predicate);
    void Add(Foo entity);
    void Delete(Foo entity);
    void Edit(Foo entity);
    void Save();
}

This repo is for Foo class I have (imaginary). Let's see the implementation for Bar class.

public interface IBarRepository {
    
    IQueryable<Bar> GetAll();
    Bar GetSingle(int barId);
    IQueryable<Bar> FindBy(Expression<Func<Bar, bool>> predicate);
    void Add(Bar entity);
    void Delete(Bar entity);
    void Edit(Bar entity);
    void Save();
}

Implementation nearly exactly the same here. Here is also an example of implementing one of these interfaces:

public class FooRepository : IFooRepository {

    private readonly FooBarEntities context = new FooBarEntities();

    public IQueryable<Foo> GetAll() {

        IQueryable<Foo> query = context.Foos;
        return query;
    }

    public Foo GetSingle(int fooId) {

        var query = this.GetAll().FirstOrDefault(x => x.FooId == fooId);
        return query;
    }

    public void Add(Foo entity) {

        context.Foos.Add(entity);
    }

    public void Delete(Foo entity) {

        context.Foos.Remove(entity);
    }

    public void Edit(Foo entity) {

        context.Entry<Foo>(entity).State = System.Data.EntityState.Modified;
    }

    public void Save() {

        context.SaveChanges();
    }
}

Also imagine this implementation for BarRepository as well. Indeed, there would be probably more repository classes for your project. After playing like that for a while I decided to do something different which still sucked but better.

A better approach but still sucks

I created a generic interface which saves me a lot of keystrokes. Here how it looks like:

public interface IGenericRepository<T> where T : class {
    
    IQueryable<T> GetAll();
    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    void Save();
}

And how I implemented in on repository interfaces:

public interface IFooRepository : IGenericRepository<Foo> {
    
    Foo GetSingle(int fooId);
}
public interface IBarRepository : IGenericRepository<Bar> {
    
    Bar GetSingle(int barId);
}

You can see that I only needed to implement GetSingle method here and others come with IGenericRepositoy<T> interface.

Where I implement these repository interfaces to my concrete classes, I still need to go over all the methods and create them individually. The repository class looked like as the same. So it leads me to a final solution which is the best one I can come up with so far.

Best approach

The generic interface I have created is still legitimate and usable here. In fact, I won’t touch the repository interfaces at all. What I did here first is to create an abstract class which implements IGenericReposity<T> interface but also accepts another type parameter defined in a generic declaration which is a type of DbConetxt class. Here is how it looks like:

public abstract class GenericRepository<C, T> : 
    IGenericRepository<T> where T : class where C : DbContext, new() {

    private C _entities = new C();
    public C Context {

        get { return _entities; }
        set { _entities = value; }
    }

    public virtual IQueryable<T> GetAll() {

        IQueryable<T> query = _entities.Set<T>();
        return query;
    }

    public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public virtual void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public virtual void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public virtual void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public virtual void Save() {
        _entities.SaveChanges();
    }
}

This is so nice because of some factors I like:

  • This implements so basic and ordinary methods
  • If necessary, those methods can be overridden because each method is virtual.
  • As we newed up the DbContext class here and expose it public with a public property, we have flexibility of extend the individual repositories for our needs.
  • As we only implement this abstract class only to our repository classes, it won’t effect unit testing at all. DbContext is not in the picture in terms of unit testing.

So, when we need to implement these changes to our concrete repository classes, we will end up with following result:

public class FooRepository :
    GenericRepository<FooBarEntities, Foo>, IFooRepository {

    public Foo GetSingle(int fooId) {

        var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
        return query;
    }
}
public class BarReposiltory : 
    GenericRepository<FooBarEntities, Bar>, IBarRepository  {

    public Bar GetSingle(int barId) {

        var query = Context.Bars.FirstOrDefault(x => x.BarId == barId);
        return query;
    }
}

Very nice and clean. Inside BarRepository GetSingle method, as you see I use Context property of GenericRepository<C, T> abstract class to access an instance of DbContext.

So, how the things work inside our ASP.NET MVC project? this is another story but no so complicated. I will continue right from here on my next post.

UPDATE:

Here is the next post:

How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking

Tags