0

I am creating project using ASP.NET Core API 2 I want to implement properly Repository Pattern and Unit of Work in separated class library. Somehow I get confuse with the implementation I only familiarize with the implementation using ASP.NET MVC 5. Please, I would like to know some suggestion also if is possible to this in ASP.NET Core 2?

Project.API

appsettings.json

{
  "ConnectionStrings": {
    "DbConnectionString": "Server=HOST; Database=DB_NAME; User Id=sa; Password=Password;"
  },
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

Startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DatninContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DbConnectionString")));

            services
                .AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        public void Configure(IApplicationBuilder applicationBuilder, IHostingEnvironment hostingEnvironment)
        {
            if (hostingEnvironment.IsDevelopment()) applicationBuilder.UseDeveloperExceptionPage();

            applicationBuilder.UseCors(AllRequests);
            applicationBuilder.UseStaticFiles();
            applicationBuilder.UseMvc();
        }
    }

Project.Persistence

EntityConfigurations Folder

public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
    {
        public void Configure(EntityTypeBuilder<Employee> builder)
        {
            throw new NotImplementedException();
        }
    }

Repositories Implementation

public class EmployeeRepository : BaseRepository<Employee>, IEmployeeRepository
    {
        public AnimeRepository(ProjectDbContext context) : base(context)
        {
        }

        public ProjectDbContext ProjectDbContext => Context as ProjectDbContext;

        public async Task<IEnumerable<Employee>> GetEmployeesAsync()
        {
            var employees = await ProjectDbContext.Employees.ToListAsync();

            return employees;
        }

        public async Task<Employee> GetEmployeeWithIdAsync(Guid id)
        {
            var employee = await DatninContext.Employees.SingleOrDefaultAsync(a => a.Id == id);

            return employee;
        }
    }

Base Repository Implementation

public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class
    {
        protected readonly DbContext Context;

        public BaseRepository(DbContext context)
        {
            Context = context;
        }

        public async Task<TEntity> GetAsync(int id)
        {
            return await Context.Set<TEntity>().FindAsync(id);
        }

        public async Task<IEnumerable<TEntity>> GetAllAsync()
        {
            return await Context.Set<TEntity>().ToListAsync();
        }

        public async Task<TEntity> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await Context.Set<TEntity>().SingleOrDefaultAsync(predicate);
        }

        public async Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await Context.Set<TEntity>().Where(predicate).ToListAsync();
        }

        public async Task AddAsync(TEntity entity)
        {
            await Context.Set<TEntity>().AddAsync(entity);
        }

        public async Task AddRangeAsync(IEnumerable<TEntity> entities)
        {
            await Context.Set<TEntity>().AddRangeAsync(entities);
        }

        public void Remove(TEntity entity)
        {
            Context.Set<TEntity>().Remove(entity);
        }

        public void RemoveRange(IEnumerable<TEntity> entities)
        {
            Context.Set<TEntity>().RemoveRange(entities);
        }
    }

ProjectDbContext.cs

public class ProjectDbContext : DbContext
    {
        public ProjectDbContext(DbContextOptions<ProjectDbContext> options) : base(options)
        {
        }

        public virtual DbSet<Employee> Employees { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

        builder.ApplyConfiguration(new EmployeeConfiguration());

        }
    }

Unit of Work Implementation

public class UnitOfWork : IUnitOfWork
    {
        private readonly ProjectDbContext _context;

        public UnitOfWork(ProjectDbContext context)
        {
            _context = context;
            Employees = new EmployeeRepository(_context);
        }

        public IEmployeeRepository Employees { get; }

        public int Complete()
        {
            return _context.SaveChanges();
        }

        public void Dispose()
        {
            _context.Dispose();
        }
    }

Propject.Core

Entities

Employee.cs

public class Employee 
    {
public int Id { get; set; }
        public string Name { get; set; }
        public string Position { get; set; }
        public string Department { get; set; }
public string Salary { get; set; }
    }

IBaseRepository.cs

public interface IBaseRepository<TEntity> where TEntity : class
    {
        Task<TEntity> GetAsync(int id);
        Task<IEnumerable<TEntity>> GetAllAsync();
        Task<TEntity> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
        Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate);
        Task AddAsync(TEntity entity);
        Task AddRangeAsync(IEnumerable<TEntity> entities);
        void Remove(TEntity entity);
        void RemoveRange(IEnumerable<TEntity> entities);
    }

IEmployeeRepository.cs

public interface IEmployeeRepository : IBaseRepository<Employee>
    {
        Task<IEnumerable<Employee>> GetEmployeesAsync();
        Task<Anime> GetEmployeeWithIdAsync(Guid id);
    }

IUnitOfWork.cs

 public interface IUnitOfWork : IDisposable
    {
        IEmployeeRepository Employees { get; }
        int Complete();
    }`
Fred
  • 223
  • 4
  • 13
  • 4
    The easiest way to do this is to **not** do it. There are too few reasons for wanting to hide EF Core behind a UoW/Repository and if you have to ask you most likely don't have those reasons. Also, you forgot to ask a question. – Camilo Terevinto Oct 12 '18 at 11:37
  • I think I really made a mistake. I thought is was good thing to do with a project. By the way what is the reason? It's not really clear to me. – Fred Oct 12 '18 at 11:55
  • Entity Framework 6 and Core implement the Repository pattern over the `DbContext` class and the UoW pattern on `DbSet`. Adding another layer is a useless complexity. Testing? Use the `InMemory` database and be done – Camilo Terevinto Oct 12 '18 at 11:58
  • That's great @CamiloTerevinto I've been doing those thing implementing REP/UOW but in the end I failed. Thank you this is a great help. – Fred Oct 12 '18 at 12:01
  • You are welcome. You may want to read [this post of mine](https://stackoverflow.com/questions/50457007/in-memory-database-doesnt-save-data/50457230#50457230) for further info – Camilo Terevinto Oct 12 '18 at 12:02
  • You have posted a whole lot of code but no clear question. Which part isn't working? "I'm confused" is not really a question. – bommelding Oct 12 '18 at 12:36
  • And yes, the whole Repo/UoW pattern is debatable. It can be useful but you need a clear reason, like a future switch of databases. – bommelding Oct 12 '18 at 12:37
  • @bommelding: I don't think it's debatable at all, actually. An ORM like Entity Framework is a *replacement* for your own custom data layer. It already implements these patterns specifically so you don't have to. If your goal is merely to abstract the EF dependency, there's better ways to do that: the service layer pattern, CQRS, microservices, etc. – Chris Pratt Oct 12 '18 at 14:00
  • Sorry, I found it is not good to re-implement the EF or EF Core. Because, it already have a implementation for REP/UOW. Somehow how can I generate migrations and good configuration for separated class library? – Fred Oct 12 '18 at 15:03
  • You can have your models, migration and DbContext in a separated class library, but still use the DbContext directly under your controller/services. – jpgrassi Oct 14 '18 at 20:56

0 Answers0