Generic Repository Methods

Today I was creating the Repositories for my demo project when I releazed that there were some methods which were present in all the interfaces of the repositories. These methods included GetById, Add, PersistAll, GetAll etc. Each of my repositories had its own interface and then they have to implement the their own custom GetById, Add, PersistAll methods. The implementation of these methods was pretty much the same with the exception of the object's type so I did not wanted to implement the same method individually for all the classes. I came up with the following class design.

Repository1

The ExamRepository is the concreate Repository class which inherits from the IExamRepository. ExamRepository also inherits from the BaseRepository class which contains the GetById, Add, PersistAll etc methods. The IExamRepository interface inherits from the IBaseRepository which means that the concreate repository must implement all the methods defined in the IExamRepository and also in the IBaseRepository. This is the reason for inheriting the IExamRepository from the BaseRepository class.

Let's check out the BaseRepository class.

 public class BaseRepository : IBaseRepository
    {
        NorthwindDataContext dc = null;

        public BaseRepository()
        {
            dc = new NorthwindDataContext();
        }

        public virtual T GetById<T>(int id) where T : class
        {
            Table<T> table = dc.GetTable<T>();           
          
            // finding the name of the PK column in the database
            MetaModel mapping = table.Context.Mapping;
            ReadOnlyCollection<MetaDataMember> members =  mapping.GetMetaType(typeof(T)).DataMembers;

            string pk = (members.Single<MetaDataMember>(m => m.IsPrimaryKey)).Name;

            // getting the object by Id
            return table.SingleOrDefault<T>
                (delegate(T t)
            {
                int memberId = (int) t.GetType().GetProperty(pk).GetValue(t, null);
                return memberId == id;

            });                   
        }

        public virtual void Add<T>(T item) where T : class
        {          
            Table<T> table = dc.GetTable<T>();
            table.InsertOnSubmit(item); 
        }

        public virtual void PersistAll()
        {
            dc.SubmitChanges();
        }      
    }

 

The method GetById<T>(int id) takes the type T. The contrainst is made because GetTable<T> only allows the reference types. The contrainst is also made in the IBaseRepository interface as shown below:

public interface IBaseRepository
    {
        T GetById<T>(int id) where T : class;
        void Add<T>(T item) where T : class;
        void PersistAll();
    }

Anyway, In the GetById method I find the name of the primary key column of the table and then uses "Anonymous Delegate" to perform the comparision.

Now, on the client side you can use the following code to get the object by Id.

  static void Main(string[] args)
        {
            IExamRepository repository = new ExamRepository();
            var category = repository.GetById<Category>(2);

            foreach (var product in category.Products)
            {
                Console.WriteLine(product.ProductName);
            }  
                                          
        }

Print | posted @ Tuesday, December 11, 2007 4:40 PM

Twitter