locked
Repository Pattern + Service Layer + Lookup Tables RRS feed

  • Question

  • User1944435642 posted

    I am implementing the Repository pattern and have interfaces like this

        public interface ICustomerRepository
        {
            IEnumerable<Customer> GetCustomers();
            void Add(Customer c);
            void Remove(Customer c);
            void Save(Customer c);
    
            Customer FindBy(int id);
        }

    The customer Repository is derived from a base Repository class and implements this interface. My service layer then uses this and any other needed repositories to perform actions.

    I have many lookup tables that will be used when a customer configures their profile: hair color, mobile phone carrier, state, county, country,  etc, etc, etc. These and other lookup tables may be used by other parts of the application.

    Each one of these lookup tables will need basic CRUD so that values maintained.

    Do I need to create a Repository for EVERY one of the lookup tables?

    Can I add a "GetStates" method in the customer repository?

    In my service layer do I create another class called "LookupService" that contains all my lookups and exposes the CRUD as needed?

    Tuesday, August 9, 2011 11:41 PM

All replies

  • User1944435642 posted

    Do I need to create a Repository for EVERY one of the lookup tables?

    I manage to use a Generic approach to this as my lookup tables will have the same format. So I do not need to create a specific class for each lookup.

        public interface ILookupRepository<T>
        {
            IEnumerable<T> FindAll();
            void Add(T c);
            void Remove(T c);
            void Save(T c);
    
            T FindBy(int id);
        }
    
        public class LookupRepository<T, EntityKey> : ILookupRepository<T>,  IUnitOfWorkRepository where T : class, IAggregateRoot
        {
            private IUnitOfWork _uow;
    
            public LookupRepository(IUnitOfWork uow)
            {
                _uow = uow;
            }
    
            public void Add(T entity)
            {
                _uow.RegisterNew(entity, this);
            }
    
            public void Remove(T entity)
            {
                _uow.RegisterRemoved(entity, this);
            }
    
            public void Save(T entity)
            {
                // Do nothing as EF tracks changes
                _uow.RegisterAmended(entity, this);
            }
    
            public IQueryable<T> GetObjectSet()
            {
                return DataContextFactory.GetDataContext().Set<T>();
            }
    
    
            public IEnumerable<T> FindAll()
            {
                return GetObjectSet().ToList<T>();
            }
    
            public IEnumerable<T> FindAll(int index, int count)
            {
                return GetObjectSet().Skip(index).Take(count).ToList<T>();
            }
    
    
            public T FindBy(int id)
            {
                System.Reflection.PropertyInfo[] properties = GetObjectSet().ElementType.GetProperties();
                System.Reflection.PropertyInfo theKey = null;
    
                foreach (System.Reflection.PropertyInfo pI in properties)
                {
                    System.Object[] attributes = pI.GetCustomAttributes(true);
                    foreach (object attribute in attributes)
                    {
                        if (attribute is KeyAttribute)
                        {
                            theKey = pI;  
                        }
                    }
                }
    
    
                if (theKey != null)
                {
                    var param = Expression.Parameter(typeof(T));
    
                    var lambda = Expression.Lambda<Func<T, bool>>
                    (
                        Expression.Equal(
                            Expression.Property(param, theKey.Name),
                            Expression.Constant(id, typeof(int))
                    ), param); 
    
                    return GetObjectSet().First(lambda);                
                }
                else
                {
                    return null;
                }
    
            }
    
            public void PersistUpdateOf(IAggregateRoot entity)
            {
                DataContextFactory.GetDataContext().Set(entity.GetType()).Attach(entity);
                DataContextFactory.GetDataContext().Entry(entity).State = System.Data.EntityState.Modified;
            }
    
    
            public void PersistCreationOf(IAggregateRoot entity)
            {
                DataContextFactory.GetDataContext().Set(entity.GetType()).Add(entity);
            }
    
    
            public void PersistDeletionOf(IAggregateRoot entity)
            {
                DataContextFactory.GetDataContext().Set(entity.GetType()).Remove(entity);
            }
        }
    
    

    Can I add a "GetStates" method in the customer repository?

    In my service layer do I create another class called "LookupService" that contains all my lookups and exposes the CRUD as needed?

    The first question here .... I will add a "GetStates" method in my service layer CustomerService class that will use ILookupRepository<State> stateRepository = LookupRepository<State, int>(this.uow) to FindAll() states

    I would like to inject the acutal stateRepository and all other lookup repositories in the contstructor for CustomerService. Does I just include EVERY repository I need in the constrcutor? What about if I have 15-20 different repositories b/c of the lookup repositories? This just doesn't seem right.

    How else does everyone deal with lookup tables?

    Any Help?

    Wednesday, August 10, 2011 7:03 PM