Wednesday, March 7, 2012

Repository Pattern with LINQ to SQL

As a continuation of my earlier post, this post aims to implement Repository Pattern using LINQ to SQL. I am using the same NorthWind Database, but this time using dbml. I have created a Linq to SQL class file called NorthWind.dbml. From the Server Explorer in Visual Studio, I have dragged and dropped the Product Table and the Category table to the designer surface of the dbml file.

Below is the implementation of a generic Repository Pattern and a concrete implementation for it, using LINQ to SQL.


//*********************************************************************************//
//***********************Generic Repository Pattern********************************//
//*********************************************************************************//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Linq.Expressions;


namespace Application.Linq
{
    public class DataRepository<T> : IDataRepository<T>, IDataRepository where T : class
    {
        readonly NorthWindDataContext _dataContext;
        public DataRepository()
        {
            _dataContext = new NorthWindDataContext();
        }
        public virtual T GetById(int ID)
        {

            var itemParameter = Expression.Parameter(typeof(T), "item");
            var members = _dataContext.GetTable<T>().Context.Mapping.GetMetaType(typeof(T)).DataMembers;
            string pk = members.Where(m => m.IsPrimaryKey == true).First().Name;
            var whereExpression = Expression.Lambda<Func<T, bool>>
                (
                Expression.Equal(
                    Expression.Property(
                        itemParameter,
                       pk
                        ),
                    Expression.Constant(ID)
                    ),
                new[] { itemParameter }
                );
            try
            {
                return GetAll().Where(whereExpression).Single();
            }
            catch
            {
                return null;
            }

        }

        public virtual IQueryable<T> GetBySpecificKey(string KeyName, string KeyVal)
        {

            var itemParameter = Expression.Parameter(typeof(T), "item");
            var whereExpression = Expression.Lambda<Func<T, bool>>
                (
                Expression.Equal(
                    Expression.Property(
                        itemParameter,
                       KeyName
                        ),
                    Expression.Constant(KeyVal)
                    ),
                new[] { itemParameter }
                );
            try
            {
                return GetAll().Where(whereExpression).AsQueryable();
            }
            catch
            {
                return null;
            }

        }

        public virtual IQueryable<T> GetAll()
        {
            return _dataContext.GetTable<T>();
        }
        public virtual void Insert(T entity)
        {

            _dataContext.GetTable<T>().InsertOnSubmit(entity);
            _dataContext.SubmitChanges();

        }
        public virtual void Delete(T entity)
        {
            _dataContext.GetTable<T>().DeleteOnSubmit(entity);
            _dataContext.SubmitChanges();
        }
       
        IQueryable IDataRepository.GetAll()
        {
            return GetAll();
        }
        void IDataRepository.Insert(object entity)
        {
            Insert((T)entity);
        }
       
        void IDataRepository.Delete(object entity)
        {
            Delete((T)entity);
        }      
        object IDataRepository.GetById(int ID)
        {
            return GetById(ID);
        }
        IQueryable IDataRepository.GetBySpecificKey(string KeyName, string KeyVal)
        {
            return GetBySpecificKey(KeyName, KeyVal);
        }
    }
    public interface IDataRepository<T> where T : class
    {
        T GetById(int ID);
        IQueryable<T> GetAll();
        void Insert(T entity);       
        void Delete(T entity);
        IQueryable<T> GetBySpecificKey(string KeyName, string KeyVal);
    }
    public interface IDataRepository
    {
        object GetById(int ID);
        IQueryable GetAll();
        void Insert(object entity);       
        void Delete(object entity);       
        IQueryable GetBySpecificKey(string KeyName, string KeyVal);
    }
}
//*********************************************************************************//
//*************************************END*****************************************//
//*********************************************************************************//
 Now the time for concrete implementation of the pattern for the Products table:
*Note: The code below should ideally go to the Business Logic Layer. I am using Data Annotations here as I had hooked the Product Repository with an ObjectDataSource and plugged it to a simple GridView control to test the implementation.

//*********************************************************************************//
//*******************Concrete implementation for the pattern***********************//
//*********************************************************************************//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Application.Linq
{
    /// <summary>
    /// Concrete implementation of the repoistory for the Product table
    /// </summary>
    [System.ComponentModel.DataObject]
    public class ProductRepository
    {
        /// <summary>
        /// The product repository is instantiated
        /// </summary>
        readonly IDataRepository<Product> objProductRepository = new DataRepository<Product>();

        /// <summary>
        /// Get all products
        /// </summary>
        /// <returns>Returns a list of all products</returns>
        [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
        public List<Product> GetAllProducts()
        {
            return objProductRepository.GetAll().ToList<Product>();
        }
      
        /// <summary>
        /// Delete a product
        /// </summary>
        /// <param name="p">The product entity to be deleted</param>
        [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Delete, true)]
        public void DeleteProduct(Product p)
        {
            objProductRepository.Delete(p);
        }

        /// <summary>
        /// Gets a product by ID, assuming the Product ID is unique
        /// </summary>
        /// <param name="ProductID">The value for the primary key ProductID</param>
        /// <returns>The product associated with the integer ID</returns>
        [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
        public Product GetProductByID(int ProductID)
        {
            try
            {
                return objProductRepository.GetById(ProductID);
            }
            catch
            {
                return null;
            }
        }
    }
}

//*********************************************************************************//
//*************************************END*****************************************//
//*********************************************************************************//

Using the concrete implementation with a GridView:


No comments: