.netasp.net-corerepositoryasp.net-identityrepository-pattern

How to Create a Generic Repository in C# that Handles Both BaseEntity and IdentityUser<int> Types?


I am developing a management system and I am using the identity library for members. But I have a problem that I could not overcome. I have my own repository structure here and I need to use this structure for the users that I create with the identity library. My repository classes are designed to work for types that inherit the BaseEntity class. However, I want to use the same repository with IdentityUser types. Since the IdentityUser class does not inherit the BaseEntity class, what kind of solution can I implement to work with this class in a compatible way? Should I provide a solution by using two separate repository classes?

public class AppUser :  IdentityUser<int>, BaseEntity
    {
        ...
    }
namespace HospitalManagement.Application.Repositories
{
    public interface IRepository<T> where T : BaseEntity
    {
        DbSet<T> Table { get; }
    }
}
namespace HospitalManagement.Application.Repositories
{
    public interface IReadRepository<T> : IRepository<T> where T : BaseEntity
    {
      ...
    }
}
namespace HospitalManagement.Application.Repositories
{
    public interface IWriteRepository<T> : IRepository<T> where T : BaseEntity
    {
       ...
    }
}

Solution

  • You can make a custom user class called AppUser that inherits from both IdentityUser and your BaseEntity in order to connect the IdentityUser class with your current repository structure. By using this approach, you can continue using your current repository pattern without having to design new repository classes. Here's how to make this happen:

    public class AppUser : IdentityUser<int>, BaseEntity
    {
        ...
    }
    

    To handle AppUser, implement the repository classes.

    namespace HospitalManagement.Application.Repositories
    {
        public interface IRepository<T> where T : BaseEntity
        {
            DbSet<T> Table { get; }
            ...
        }
        
        public interface IReadRepository<T> : IRepository<T> where T : BaseEntity
        {
          ...
        }
    
        public interface IWriteRepository<T> : IRepository<T> where T : BaseEntity
        {
            ...
        }
    }
    
    public class Repository<T> : IRepository<T> where T : BaseEntity
    {
        protected readonly DbContext _context;
    
        public Repository(DbContext context)
        {
            _context = context;
        }
    
        public DbSet<T> Table => _context.Set<T>();
    
       ...
    }
    
    public class ReadRepository<T> : Repository<T>, IReadRepository<T> where T : BaseEntity
    {
        public ReadRepository(DbContext context) : base(context) { }
        ...
    }
    
    public class WriteRepository<T> : Repository<T>, IWriteRepository<T> where T : BaseEntity
    {
        public WriteRepository(DbContext context) : base(context) { }
        ...
    }
    

    When you need to use the AppUser in your repositories, you can now do so directly:

    public class UserRepository : IWriteRepository<AppUser>, IReadRepository<AppUser>
    {
        private readonly DbContext _context;
    
        public UserRepository(DbContext context)
        {
            _context = context;
        }
    
        public DbSet<AppUser> Table => _context.Set<AppUser>();
    
        
    }