none
EF 4.1 design/pattern question for custom queries RRS feed

  • Question

  • Hello,

    I’m using EF 4.1 code first for my project and until now all works fine, but I have a design question. I have read that DBContext and DBSet are some kind of repository and unit of work pattern and for my simple application I think it’s not worth to implement my custom repository and unit of works. But no I have the following question: Where can I put my custom queries?

    I have for example my Customer class and Customers DbSet exposed by my context. I want to encapsulate a query that returns all active Customers ordered by Name (getActiveCustomers)

    What is the best place to put this method?

    I have considered putting it on my "customer" class, but I think it’s not a good idea because I need the context to get the entities.

    Another solution would be to put this function on my context class, but I want to have all my queries related to customers together.

    The third option could be to create a custom DBSet (inherited form DBSet) that has this method, but I’m not sure if this has other problems.

    Thanks for your replays,

    Alex B.

    Thursday, December 1, 2011 8:27 AM

Answers

  • Hi Alex,

    if you are using unit of work and repository pattern it should be easy to add custom repositories for each entity you need.. The place where I store custom queries in this architecture are derived repositorys like this:

    [Service(typeof(IUserRepository), ServiceBehaviour.Request)]
        public class UserRepository : Repository<User>, IUserRepository
        {

    The IUserRepository declares those custom repository methods. The generic base repository allows to read from any entity.

      public abstract class Repository<TEntity> : IRepository<TEntity>
            where TEntity : class
        {

    If you are interested in detail.. I uploaded a small demo app that implements this architecture in a way I suggest for MVC applications..

    https://github.com/dixus/Mvc3EFUnity

    HTH

    Holger


    • Edited by Holger Kreissl Thursday, December 1, 2011 12:13 PM
    • Proposed as answer by Joba Diniz Thursday, December 1, 2011 6:02 PM
    • Marked as answer by Alex Bibiano Friday, December 2, 2011 5:32 AM
    Thursday, December 1, 2011 12:12 PM

All replies

  • Hi Alex,

    if you are using unit of work and repository pattern it should be easy to add custom repositories for each entity you need.. The place where I store custom queries in this architecture are derived repositorys like this:

    [Service(typeof(IUserRepository), ServiceBehaviour.Request)]
        public class UserRepository : Repository<User>, IUserRepository
        {

    The IUserRepository declares those custom repository methods. The generic base repository allows to read from any entity.

      public abstract class Repository<TEntity> : IRepository<TEntity>
            where TEntity : class
        {

    If you are interested in detail.. I uploaded a small demo app that implements this architecture in a way I suggest for MVC applications..

    https://github.com/dixus/Mvc3EFUnity

    HTH

    Holger


    • Edited by Holger Kreissl Thursday, December 1, 2011 12:13 PM
    • Proposed as answer by Joba Diniz Thursday, December 1, 2011 6:02 PM
    • Marked as answer by Alex Bibiano Friday, December 2, 2011 5:32 AM
    Thursday, December 1, 2011 12:12 PM
  • A lot of thanks. I was actualy not implementing the repository pattern and unit of work but after looking at your code I have done it this way and hve solved my problems.

    Your code is very easy to understand. After implementing this patterns I have added my custom queries to the concrete repository of every entity.

    I have one questoion about your implementation of the repository pattern. I have implemented for example a concrete ProductRepository and with GetAll I can get all entities (products).

    I have also an Family Entity (each product belogns to a Family). What do you think is the best aproach to get all families to fill a dropdown control?

    1. Implement his own repository and get the list with GetAll

    2. Create some GetFamilies method in the ProductgRepository to return the list

    If option 2 is used, how can I get entities from other DBSet's in a repository created with your abstract IRepository?

    Thanks,

     

    Alex B.

    Friday, December 2, 2011 5:39 AM
  • Hi Alex,

    with the generic repository it doesnt matter which entity you are using to GetAll.. Maybe I dont understand your questsion correntely.. But IRepository<TEntity> means you can create instances for every entity. Only need is that the DbSet must be is a property of your DbContext implementation.. So you can use the generic GetAll or GetMany instead of a specialized GetFamliles.. And you can access all DbSets with that generic repository..

    Greets

    Holger

     

    Friday, December 2, 2011 8:40 AM
  • My question was if I need to create a repository for every Entity (I have a lot of lookup tables with only 2 fields).

    I have already found a solution. I have created a SimpleRepository inherited form your generic repository that I can use to query this simple entities without the need of creating a repositori for every entity

        public interface ISimpleRepository<T> : IRepository<T>
            where T: class
        {
        }
    
        public class SimpleRepository<TEntity> : Repository<TEntity> , ISimpleRepository<TEntity>
            where TEntity : class
        {
            public SimpleRepository(IDatabaseFactory databaseFactory)
                : base(databaseFactory)
            {
            }
        }
    

     And I can use it with this code:

    using (IDatabaseFactory _factory = new DatabaseFactory())
    {
    	IProductoRepository _repositoryProductos = new ProductoRepository(_factory);
    	IList<Producto> _productos = _repositoryProductos.GetAll().ToList();
    	foreach (Producto producto in _productos)
    	{
    		Console.WriteLine("{0}", producto.descripcion);
    	}
    
    	<strong>ISimpleRepository<TipoLabio> _repositorioTipoLabios = new SimpleRepository<TipoLabio>(_factory);</strong>
    	IList<TipoLabio> _tiposLabio = _repositorioTipoLabios.GetAll().ToList();
    
    	foreach (TipoLabio tipoLabio in _tiposLabio)
    	{
    		Console.WriteLine("{0} {1}", tipoLabio.idTipoLabio, tipoLabio.nombre);
    	}
    }
    Console.ReadKey();
    

    Do you see drawbacks in my solution?

    Thanks for your time

     

    Alex B.

    Friday, December 2, 2011 9:13 AM
  • yea think i missunderstood you.. I dont see any drawbacks in this code... as long as your repositories derive from the generic one, it should be exactely the way I suggested earlier..

    Have a nice day

    Holger

    Friday, December 2, 2011 9:24 AM