Skip to content

Repository inheritance

anton-martyniuk edited this page Oct 26, 2022 · 3 revisions

Modern generic repositories are flexible, easily changeable and extendable. New methods can be added to repository as well as each method can be overriden.

Inherit from the following interfaces:

IModernCrudRepository<TEntity, TId>
IModernQueryRepository<TEntity, TId>

Or inherit from a combined interface:

IModernRepository<TEntity, TId> : IModernCrudRepository<TEntity, TId>, IModernQueryRepository<TEntity, TId>

Lets have a look at example of inheritance from ModernEfCoreRepository:

public interface IAirplaneRepository : IModernRepository<AirplaneDbo, long>
{
}

public class AirplaneRepository : ModernEfCoreRepositoryWithFactory<FlyingDbContext, AirplaneDbo, long>, IAirplaneRepository
{
    public AirplaneRepository(IDbContextFactory<FlyingDbContext> dbContextFactory, IOptions<EfCoreRepositoryConfiguration?> configuration)
        : base(dbContextFactory, configuration)
    {
    }

    // Override GetEntityId
    protected override long GetEntityId(AirplaneDbo entity) => entity.Id;

    // Override GetEntityIncludeQuery to include Airplane Model
    protected override EntityIncludeQuery<AirplaneDbo> GetEntityIncludeQuery()
        => new(query => query.Include(t => t.Model));
    
    // Override CreateAsync to select existing Airplane Model
    public override async Task<AirplaneDbo> CreateAsync(AirplaneDbo entity, CancellationToken cancellationToken = default)
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync(cancellationToken);
        var model = await dbContext.AirplaneModels.FirstOrDefaultAsync(x => x.Name == entity.Model.Name, cancellationToken);
        if (model is not null)
        {
            entity.Model = model;
        }

        await dbContext.Airplanes.AddAsync(entity, cancellationToken);
        await dbContext.SaveChangesAsync(cancellationToken);

        return entity;
    }

    // Override CreateAsync(list) to select existing Airplane Model
    public override async Task<List<AirplaneDbo>> CreateAsync(List<AirplaneDbo> entities, CancellationToken cancellationToken = default)
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync(cancellationToken);

        foreach (var entity in entities)
        {
            var model = await dbContext.AirplaneModels.FirstOrDefaultAsync(x => x.Name == entity.Model.Name, cancellationToken);
            if (model is not null)
            {
                entity.Model = model;
            }

            await dbContext.Airplanes.AddAsync(entity, cancellationToken);
        }
        
        await dbContext.SaveChangesAsync(cancellationToken);

        return entities;
    }
}

Lets have a look at example of inheritance from ModernDapperRepository:

public interface IAirplaneDapperRepository : IModernRepository<AirplaneDbo, long>
{
}

public class AirplaneDapperRepository : ModernDapperRepository<AirplaneDapperMapping, AirplaneDbo, long>, IAirplaneDapperRepository
{
    public AirplaneDapperRepository(IDbConnectionFactory connectionFactory, AirplaneDapperMapping mapping, IQueryProviderFactory factory)
        : base(connectionFactory, mapping, factory)
    {
    }
}

Lets have a look at example of inheritance from ModernMongoDbRepository:

public interface IAirplaneMongoDbRepository : IModernRepository<AirplaneDbo, string>
{
    Task<IEnumerable<AirplaneDbo>> GetNewAirplanesAsync();
}

public class AirplaneMongoDbRepository : ModernMongoDbRepository<AirplaneDbo, string>, IAirplaneMongoDbRepository
{
    public AirplaneMongoDbRepository(IMongoClient client)
        : base(client, "tourism", "airplanes")
    {
    }

    protected override string GetEntityId(AirplaneDbo entity) => entity.Id;

    public async Task<IEnumerable<AirplaneDbo>> GetNewAirplanesAsync()
    {
        return await MongoCollection.Find(x => x.YearOfManufacture > 2010).ToListAsync();
    }
}
Clone this wiki locally