Mar 29

Generic Repository Pattern and Unit of Work

1.    Introduction

In this post I am going to introduce the Generic Repository Pattern and Unit Of Work. Actually, I am going to develop an application for an Employee entity on which we can do Create, Read, Update and Delete operation. Suppose, we have an large enterprise application which contains more than one entity, then we need to create repository for each entity which is tedious job and even not easy for maintenance. To avoid repeating the code for each entity’s repository we are creating this Generic  Repository. In this post we will see how to implement a decoupled, unit-testable and N-Tier architecture based Repository Pattern with entity framework.

2.    Overview

The first question comes into your mind is that What is Repository pattern?. It is an abstract data access layer for the application which allows to centralize all data access login in one place. With generic future, we can reduce the amount of code that we generally uses for common scenarios like Create, Update, Delete, Get All and selecting single record. It is an data access pattern which uses loosely-coupled approach to access data.
The Unit Of Work(or simply UOW) class creates the repository instance for each entity and the repository used for CRUD operation. The following diagram shows the relationship between the repository and the entity framework data context in which your business layer interact with repository by a Unit Of Work rather than by directly with the entity framework.

3.    Practical Implementation

To start with this implementation lets create a database “Generic Repository” and create Employee table.
USE [master]
GO
CREATE DATABASE [GenericRepository]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N’GenericRepository’, FILENAME = N’c:Program FilesMicrosoft SQL ServerMSSQL11.SQLEXPRESSMSSQLDATAGenericRepository.mdf’ , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON
( NAME = N’GenericRepository_log’, FILENAME = N’c:Program FilesMicrosoft SQL ServerMSSQL11.SQLEXPRESSMSSQLDATAGenericRepository_log.ldf’ , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [GenericRepository] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY(‘IsFullTextInstalled’))
begin
EXEC [GenericRepository].[dbo].[sp_fulltext_database] @action = ‘enable’
end
GO
ALTER DATABASE [GenericRepository] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [GenericRepository] SET ANSI_NULLS OFF
GO
ALTER DATABASE [GenericRepository] SET ANSI_PADDING OFF
GO
ALTER DATABASE [GenericRepository] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [GenericRepository] SET ARITHABORT OFF
GO
ALTER DATABASE [GenericRepository] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [GenericRepository] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [GenericRepository] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [GenericRepository] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [GenericRepository] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [GenericRepository] SET CURSOR_DEFAULT  GLOBAL
GO
ALTER DATABASE [GenericRepository] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [GenericRepository] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [GenericRepository] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [GenericRepository] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [GenericRepository] SET  DISABLE_BROKER
GO
ALTER DATABASE [GenericRepository] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [GenericRepository] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [GenericRepository] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [GenericRepository] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [GenericRepository] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [GenericRepository] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [GenericRepository] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [GenericRepository] SET RECOVERY SIMPLE
GO
ALTER DATABASE [GenericRepository] SET  MULTI_USER
GO
ALTER DATABASE [GenericRepository] SET PAGE_VERIFY CHECKSUM 
GO
ALTER DATABASE [GenericRepository] SET DB_CHAINING OFF
GO
ALTER DATABASE [GenericRepository] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [GenericRepository] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
USE [GenericRepository]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Employee](
       [Id] [int] IDENTITY(1,1) NOT NULL,
       [FirstName] [nvarchar](50) NULL,
       [LastName] [nvarchar](50) NULL,
       [Email] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
       [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [master]
GO
ALTER DATABASE [GenericRepository] SET  READ_WRITE
GO
In this post we will create three projects i.e. Domain, DataAccessLayer and TestClient to test the work done. In this post we work with entity framework code first approach. So the project domain contains the entities that are need for this application. In Domain project we will create Employee entity and it’s mapping with database. DataAccessLayer will contains Repository and Unit of Work related classes and Test client contains service to call repository and main function. Below figure shows the overall project architecture.
Create Domain project and reference of Entity Framework 6.0 using nuget package manager. Add reference of System.ComponentModel.DataAnnotations for fluent validation.
Create Employee entity in Domain project.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Domain
{
    public class Employee
    {
        public int Id { get; set; }
        [StringLength(50)]
        public string FirstName { get; set; }
        [StringLength(50)]
        public string LastName { get; set; }
        [StringLength(50)]
        public string Email { get; set; }
    }
}
Define the configuration for the Employee entity that will be used when the database will be mapped with  the entity. This EmployeeMap configuration is placed inside Mapping folder of Domain project. Allows configuration to be performed for an entity type in a model.  An EntityTypeConfiguration can be obtained via the Entity method on System.Data.Entity.DbModelBuilder or a custom type derived from EntityTypeConfiguration can be registered via the Configurations property on System.Data.Entity.DbModelBuilder.
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
namespace Domain.Mapping
{
    public class EmployeeMap : EntityTypeConfiguration<Employee>
    {
        public EmployeeMap()
        {
            // Primary Key
            this.HasKey(t => t.Id);
            // Properties
            this.Property(t => t.FirstName)
                .IsRequired()
                .HasMaxLength(50);
            this.Property(t => t.LastName)
               .IsRequired()
               .HasMaxLength(50);
            this.Property(t => t.Email)
              .IsRequired()
              .HasMaxLength(50);
            // Table & Column Mappings
            this.ToTable(“Employee”);
            this.Property(t => t.Id).HasColumnName(“Id”);
            this.Property(t => t.FirstName).HasColumnName(“FirstName”);
            this.Property(t => t.LastName).HasColumnName(“LastName”);
            this.Property(t => t.Email).HasColumnName(“Email”);
        }
    }
}
The DataAccessLayer project contains DataContext, Employee entity Mapping, Repository and Unit of Work classes. The ADO.NET Entity Framework Code First data access approach requires us to create a data access context class that inherits from the DbContext class so we create a context class GenericRepositoryDBContext class. In this class, we override the OnModelCreating() method. This method is called when the model for a context class (GenericRepositoryDBContext) has been initialized, but before the model has been locked down and used to initialize the context such that the model can be further configured before it is locked down. The following is the code snippet for the context class.
As you know, the EF Code First approach follows convention over configuration, so in the constructor, we just pass the connection string name, the same as an App.Config file and it connects to that server. In the OnModelCreating() method, we used reflection to map an entity(Domain.dll) to its configuration class in this specific project.
  <connectionStrings>
    <add name=GenericRepositoryDBContext connectionString=Data Source=USER-VAIOSQLEXPRESS;Initial Catalog=GenericRepository;Integrated Security=True providerName=System.Data.SqlClient />
  </connectionStrings>
Create DataAccessLayer Project and add below files.
using System;
using System.Configuration;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Reflection;
namespace DataAccessLayer
{
    /// <summary>
    /// The main context class that checks the domain model wrt database.
    /// </summary>
    public class GenericRepositoryDBContext : DbContext
    {
        /// <summary>
        /// Initializes the <see cref=”GenericRepositoryDBContext”/> class.
        /// </summary>
        static GenericRepositoryDBContext()
        {
            System.Data.Entity.Database.SetInitializer<GenericRepositoryDBContext>(null);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref=”GenericRepositoryDBContext”/> class.
        /// </summary>
        public GenericRepositoryDBContext()
            : base(“GenericRepositoryDBContext”)
        {
           
        }
        /// <summary>
        /// This method is called when the model for a derived context has been initialized, but
        /// before the model has been locked down and used to initialize the context.  The default
        /// implementation of this method does nothing, but it can be overridden in a derived class
        /// such that the model can be further configured before it is locked down.
        /// </summary>
        /// <param name=”modelBuilder”>The builder that defines the model for the context being created.</param>
        /// <remarks>
        /// Typically, this method is called only once when the first instance of a derived context
        /// is created.  The model for that context is then cached and is for all further instances of
        /// the context in the app domain.  This caching can be disabled by setting the ModelCaching
        /// property on the given ModelBuidler, but note that this can seriously degrade performance.
        /// More control over caching is provided through use of the DbModelBuilder and DbContextFactory
        /// classes directly.
        /// </remarks>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            var typesToRegister = Assembly.Load(“Domain”).GetTypes()
                                .Where(type => !String.IsNullOrEmpty(type.Namespace))
                                .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
           
            foreach (var type in typesToRegister)
            {
                dynamic configurationInstance = Activator.CreateInstance(type);
                modelBuilder.Configurations.Add(configurationInstance);
            }
            base.OnModelCreating(modelBuilder); 
        }
    }
}
Now, let’s create and IRepository<T> interface which provides basic method required for CRUD operation.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace DataAccessLayer
{
    /// <summary>
    /// Generic repository class that defineds operation related to CRUD.
    /// </summary>
    /// <typeparam name=”T”></typeparam>
    public interface IRepository<T> : IDisposable
    {
        /// <summary>
        /// Gets the by identifier.
        /// </summary>
        /// <param name=”id”>The identifier.</param>
        /// <returns></returns>
        T GetById(int id);
        /// <summary>
        /// Gets all.
        /// </summary>
        /// <returns></returns>
        IQueryable<T> GetAll();
        /// <summary>
        /// Gets all.
        /// </summary>
        /// <param name=”index”>The index.</param>
        /// <param name=”count”>The count.</param>
        /// <returns></returns>
        IQueryable<T> GetAll(int index, int count);
        /// <summary>
        /// Updates the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        void Update(T entity);
        /// <summary>
        /// Inserts the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        void Insert(T entity);
        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        void Delete(T entity);
    }
}
Now implement the IRepository<T> interface in Repository<T> class. This repository contains the parameterized constructor with parameter context. So when we create an instance of repository we pass the context so that all repositories of each entity has the same context.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
namespace DataAccessLayer
{
    /// <summary>
    ///  Generic repository class that defineds operation related to CRUD.
    /// </summary>
    /// <typeparam name=”T”></typeparam>
    public class Repository<T> : IRepository<T> where T : class
    {
        public DbContext context;
        public DbSet<T> dbSet;
        /// <summary>
        /// Initializes a new instance of the <see cref=”Repository{T}”/> class.
        /// </summary>
        /// <param name=”context”>The context.</param>
        public Repository(DbContext context)
        {
            this.context = context;
            dbSet = context.Set<T>();
        }
        /// <summary>
        /// Gets the by identifier.
        /// </summary>
        /// <param name=”id”>The identifier.</param>
        /// <returns></returns>
        public T GetById(int id)
        {
            return dbSet.Find(id);
        }
        /// <summary>
        /// Gets all.
        /// </summary>
        /// <returns></returns>
        public IQueryable<T> GetAll()
        {
            return dbSet;
        }
        /// <summary>
        /// Gets all.
        /// </summary>
        /// <param name=”index”></param>
        /// <param name=”count”></param>
        /// <returns></returns>
        public IQueryable<T> GetAll(int index, int count)
        {
            return dbSet.Skip(index).Take(count);
        }
        /// <summary>
        /// Inserts the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        public void Insert(T entity)
        {
            dbSet.Add(entity);
        }
        /// <summary>
        /// Updates the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        public void Update(T entity)
        {
            context.Entry(entity).State = EntityState.Modified;
        }
        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name=”entity”>The entity.</param>
        public void Delete(T entity)
        {
            context.Entry(entity).State = EntityState.Deleted;
        }
        private bool disposed = false;
        /// <summary>
        /// Releases unmanaged and – optionally – managed resources.
        /// </summary>
        /// <param name=”disposing”><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}
Now let’s create the IUnitOfWork interface which provide common repository property and Save method.
namespace DataAccessLayer
{
    /// <summary>
    /// This is the wrapper around repositiry. This creates the instance of context and returns the repository called.
    /// </summary>
    public interface IUnitOfWork
    {
        /// <summary>
        /// Repositories this instance.
        /// </summary>
        /// <typeparam name=”T”></typeparam>
        /// <returns></returns>
        IRepository<T> Repository<T>() where T : class;
        /// <summary>
        /// Saves this instance.
        /// </summary>
        void Save();
    }
}
Now, implement the IUnitOfWork interface in UnitOfWork class which inherits from IDisposable interface so that it’s instance will be disposed after calling the repository. This class initiates the application DataContext(GenericRepositoryDBContext). The Repository() method that returns the repository for the entity.
using System;
using System.Collections.Generic;
using Domain;
namespace DataAccessLayer
{
    /// <summary>
    /// This is the wrapper around repositiry. This creates the instance of context and returns the repository called.
    /// </summary>
    public class UnitOfWork : IDisposable, IUnitOfWork
    {
        private bool disposed;
        private Dictionary<string, object> repositories;
        private GenericRepositoryDBContext context;
        /// <summary>
        /// Initializes a new instance of the <see cref=”UnitOfWork”/> class.
        /// </summary>
        public UnitOfWork()
        {
            context = new GenericRepositoryDBContext();
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// Releases unmanaged and – optionally – managed resources.
        /// </summary>
        /// <param name=”disposing”><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        public virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            disposed = true;
        }
        /// <summary>
        /// Repositories this instance.
        /// </summary>
        /// <typeparam name=”T”></typeparam>
        /// <returns></returns>
        public IRepository<T> Repository<T>() where T : class
        {
            if (repositories == null)
            {
                repositories = new Dictionary<string, object>();
            }
            var type = typeof(T).Name;
            if (!repositories.ContainsKey(type))
            {
                var repositoryType = typeof(Repository<>);
                var repositoryInstance = Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), context);
                repositories.Add(type, repositoryInstance);
            }
            return (Repository<T>)repositories[type];
        }
        /// <summary>
        /// Saves this instance.
        /// </summary>
        public void Save()
        {
            context.SaveChanges();
        }
    }
}
Now, create the TestClient project to test the generic repository created. This project contains Employee Service which is used for Employee entities CRUD operation. We first create a Unit of Work class instance then the Employee Service constructor initiates the repository as per the required employee entity. The Save() method of repository will be used to save entity into database.
using System.Collections.Generic;
using System.Linq;
using DataAccessLayer;
using Domain;
namespace TestClient
{
    /// <summary>
    /// The CRUD operation of employee
    /// </summary>
    public class EmployeeService
    {
        private UnitOfWork unitOfWork = new UnitOfWork();
        private IRepository<Employee> employeeRepository;
        /// <summary>
        /// Initializes a new instance of the <see cref=”EmployeeService”/> class.
        /// </summary>
        public EmployeeService()
        {
            employeeRepository = unitOfWork.Repository<Employee>();
        }
        /// <summary>
        /// Gets the by identifier.
        /// </summary>
        /// <param name=”id”>The identifier.</param>
        /// <returns></returns>
        public Employee GetById(int id)
        {
            return employeeRepository.GetById(id);
        }
        /// <summary>
        /// Gets all.
        /// </summary>
        /// <returns></returns>
        public List<Employee> GetAll()
        {
            return employeeRepository.GetAll().ToList();
        }
        /// <summary>
        /// Creates the specified employee.
        /// </summary>
        /// <param name=”employee”>The employee.</param>
        /// <returns></returns>
        public int Create(Employee employee)
        {
            employeeRepository.Insert(employee);
     unitOfWork.Save();
        
            return employee.Id;
        }
        /// <summary>
        /// Updates the specified employee.
        /// </summary>
        /// <param name=”employee”>The employee.</param>
        public void Update(Employee employee)
        {
            employeeRepository.Update(employee);
            unitOfWork.Save();
        }
        /// <summary>
        /// Deletes the specified employee.
        /// </summary>
        /// <param name=”employee”>The employee.</param>
        public void Delete(Employee employee)
        {
            employeeRepository.Delete(employee);
            unitOfWork.Save();
        }
    }
}
Please find below application config files details that we need to do.
<?xml version=1.0 encoding=utf-8?>
<configuration>
  <configSections>
    <!– For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 –>
    <section name=entityFramework type=System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 requirePermission=false />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type=System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework />
    <providers>
      <provider invariantName=System.Data.SqlClient type=System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer />
    </providers>
  </entityFramework>
  <connectionStrings>
    <add name=GenericRepositoryDBContext connectionString=Data Source=USER-VAIOSQLEXPRESS;Initial Catalog=GenericRepository;Integrated Security=True providerName=System.Data.SqlClient />
  </connectionStrings>
</configuration>
Now, create a small program to test the EmployeeService.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain;
namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
           
            var employeeService = new EmployeeService();
            Console.WriteLine(“———–TOTAL NUMBER OF EMPLOYEES———–n”);
            // Display total list of employee
            Console.WriteLine(string.Format(“The total number of employee are: {0}”, employeeService.GetAll().Count));
            Console.WriteLine(“n——–CREATING EMPLOYEE————n”);
            // Create Employee
            var employee = new Employee { FirstName = “Rohit”, LastName = “Nadhe”, Email = “rohit@email.com” };
            var employeeId = employeeService.Create(employee);
            // Display total list of employee
            Console.WriteLine(string.Format(“The total number of employee are: {0}”, employeeService.GetAll().Count));
            Console.WriteLine(“n————–DISPLAYING CREATED EMPLOYEE DETAILS———–n”);
            //Display created employee
            var employeeDetails = employeeService.GetById(employeeId);
            Console.WriteLine(string.Format(“Employee details are: First Name: {0}, Last Name:{1}, Email: {2}”, employeeDetails.FirstName, employeeDetails.LastName, employeeDetails.Email));
            Console.WriteLine(“n———–UPDATING EMPLOYEE DETAILS————n”);
            // Update employee details
            employeeDetails.FirstName = “Rohit 1”;
            employeeDetails.LastName = “Nadhe 1”;
            employeeService.Update(employeeDetails);
            Console.WriteLine(“n———UPDATED EMPLOYEE DETAILS——–n”);
            employeeDetails = employeeService.GetById(employeeId);
            Console.WriteLine(string.Format(“Updated Employee details are: First Name: {0}, Last Name:{1}, Email: {2}”, employeeDetails.FirstName, employeeDetails.LastName, employeeDetails.Email));
            Console.WriteLine(“n———DELETING EMPLOYEE——–n”);
            //Delete employee
            employeeService.Delete(employeeDetails);
            Console.WriteLine(“n——–TOTAL NUMBER OF EMPLOYEES——-n”);
            // Display total list of employee
            Console.WriteLine(string.Format(“The total number of employee are: {0}”, employeeService.GetAll().Count));
                      
            Console.ReadKey();
        }
    }
}
After running the application first time it will show below results serially.
1.       First no record exist in database hence, showing zero(0) records in the system.
2.       Create an employee using Create() method of repository and call GetAll() method of repository which will display one record, means record successfully created.
3.       Display the created record on console using GetById() method.
4.       Now update the last inserted record using Update() method and display record using GetById()
5.       Now delete the last inserted record using Delete() method of repository and call GetAll() method to see how many record exist in system.
Below figure shows the actual execution and console output.
 

4.    Summary

In this post we learned the Generic Repository and Unit Of Work pattern. I hope you enjoyed the post article. Feel free to share your thoughts in the comment box.
In my next article I will show you how to use service(business) layer to call repository and dependency injection using Microsoft Unity framework.

10 comments

Skip to comment form

  1. Hi. Nevertheless for each entity like User, Employee etc.. i still need service class, is this correct? For instance for Employee you created EmployeService which seems to be EmployeDal in fact.

    1. Yes Robert you are correct!. To make it loosely coupled architecture you need service class and you can inject service dependency through constructor. In me next article I will show below approaches with same example.

      1. Controller/Client=> Business Layer=>Data Layer(using generic repository)=>SQL Server
      2. Controller/Client=>WebAPI/WCF Service => Business Layer=>Data Layer(using generic repository)=>SQL Server

      In my next article, I will show how to achieve it. Currently, I am busy in learning Angular 5 hence couldn’t posted posts. Apologize for delayed response.

      1. Question1: So in this case we would have one generic service for all entities whichi would avoid to create separated service for each entity right?

        Q2: I have some code which you could use (some part also from you articles) maybe you could take a look and use in your next article – i have troubles to put all together but i am sure with your help this could be relly nice. What do you think can i share with you somehow?

        1. Answer 1: Yes we can create one generic service class(only for CRUD) on top and from that we can call functions of generic repository. If you have specific implementation then that would go to concrete class.

          Answer 2: This is very basic generic repository pattern i have explained. In my next article i will show 30 more generic functions for .Net and same 30 for .Net Core but those article will take more time to come as i am explaining it serially. Besides this i have also written generic repository for asynchronous functions. Be patient it will coming soon!!

          In last couple of months I have not written any post(due to illness and some personal commitments) but once I start I will try to finish number of posts which are in draft version.

          I am glad that my article helped you in some extent.

          Cheers!

          1. I have question but i need somehow to show you the code – i think you will understand that easly. How could i show it to you?

  2. If you still active please give some answer 🙂

  3. I am thinking if there wouldn;t be EF context used in Repositoty but for instance Sql Server then public DbSet dbSet; cannot be used because then in this case Employee is easly cast to this variable, otherwise if oracle or Sql server how would you handle this type on Repository for instance Employee ot for instance Product? I am would really love that to see. Morover to have not every service per business type like User –> UserService, Employee–> EmployeeService but something like GenericService that every business object could custom + to see bonus business class like ExtraClass which GenericService could be extended or something. is it possible to create such topic?

    1. Robert we can sit together this weekend. You can drop me email on consultant.rohitn@gmail.com

    2. Generic service could break the single responsibility pattern rule. Hence I would suggest to create baseservice to access generic repository and perform only CRUD.
      Anyways we will sit together this weekend to discuss this..

  4. Thanks for great tutorial. I have some questions here:

    1. Seems that for all three projects entity framework has to be installed, is it normal?
    2. If it’s code first approach. Let’s say Employee table will change, what should be the process to implement the change. Should it be done from code and then somehow update database from visual studio? Please of describtion. P.S Either one approach or another is it also possible both way?

Leave a Reply