NET 6 - Interfaces and Services

Last modified: June 21, 2021

An interface is similar to a class except it is purely represents a contract between an object and user. We do not put the implementation of a method in the interface file, just the signature.

1. Add Interfaces

  • Select TicketingSystem.Core project
  • Create an Interfaces folder
  • Add new GenericRepository interface by right-clicking on TicketingSystem.Core project and add new interface as shown below

interface interface

public interface IGenericRepository<T> where T : class { Task<T?> GetById(string id); Task<IEnumerable<T>> GetAll(); Task<bool> Add(T entity); Task<bool> Remove(string id); Task<bool> Update(T entity); }
  • We do same above steps to create IEventRepository and IEventBookingRepository interfaces.

IEventRepository

public interface IEventRepository : IGenericRepository<Event> { }

IEventBookingRepository

public interface IEventBookingRepository : IGenericRepository<EventBooking> { }

2. Services

Service is the implementation of the interface. The benefit of using Interface and Service to implement the business logic is we can easily swap the implementation. One good example is that ASP.NET 6 has bult-in logging. To implement another logging (e.g. log4net or Serilog);

  • Add DbContext

  • Select TicketingSystem.Infrastructure project

  • We need to install EntityFrameworkCore NuGet Package

Implementation

  • We also neeed to install EntityFrameworkCore.SqlServer NuGet Package to connect to SQL Server Database

Implementation

  • Add TicketingSystem.Core project reference to TicketingSystem.Infrastructure project

    • Add Project Reference
    • Select TicketingSystem.Core

    Implementation

  • Create a class called TicketingDbContext and replace with following code

DbContext is a bridge between your domain or entity classes and the database

public class TicketingDbContext :DbContext { public TicketingDbContext(DbContextOptions<TicketingDbContext> options) : base(options) { } public virtual DbSet<Event> Event { get; set; } public virtual DbSet<EventBooking> EventBooking { get; set; } }
  • GenericRepository
    • This is implementation of IGenericRepository interface using Entity Framwork (EF) Core
    • Create a folder Repositories in TicketingSystem.Infrastructure project
    • Create a class file named GenericRepository save it to Repositories folder

GenericRepository

We are using asynchronous methods to retrieve and save the data via context to the database.

public class GenericRepository<T> : IGenericRepository<T> where T : class { protected readonly TicketingDbContext _context; protected DbSet<T> dbSet; public GenericRepository( TicketingDbContext context ) { _context = context; dbSet = _context.Set<T>(); } public async Task<bool> Add(T entity) { try { await dbSet.AddAsync(entity); await _context.SaveChangesAsync(); return true; } catch (Exception ex) { return false; } } public async Task<IEnumerable<T>> GetAll() { return await dbSet.ToListAsync(); } public async Task<T?> GetById(string id) { return await dbSet.FindAsync(id); } public async Task<bool> Remove(string id) { var t = await dbSet.FindAsync(id); if (t != null) { dbSet.Remove(t); await _context.SaveChangesAsync(); return true; } else return false; } public async Task<bool> Update(T entity) { _context.Update(entity); await _context.SaveChangesAsync(); return true; } }
  • EventRepository

    • This is implementation of IEventRepository interface

    • Create a class file named EventRepository and save it to Repositories folder

    • EventRepository

    public class EventRepository : GenericRepository<Event>, IEventRepository { public EventRepository(TicketingDbContext context) : base(context) { } }
  • EventBookingRepository

    • This is implementation of IEventBookingRepository interface

    • Create a class file name EventBookingRepository and save it to Repositories folder

    • EventBookingRepository

    public class EventBookingRepository : GenericRepository<EventBooking>, IEventBookingRepository { public EventBookingRepository(TicketingDbContext context) : base(context) { } }