hrynco-ef

Reusable Entity Framework Core base library for HrynCo applications.

Solution

The solution (hrynco-ef.slnx) contains two projects:

Project Description
HrynCo.DAL.Abstract Infrastructure-agnostic contracts: entities, repository interfaces, unit of work, transactions, pagination. No EF Core dependency.
HrynCo.DAL.EF Entity Framework Core implementations of the abstract contracts. Depends on HrynCo.DAL.Abstract and EF Core.

The split allows consuming projects to reference only HrynCo.DAL.Abstract in domain/application layers, keeping those layers free of EF Core.

Versioning

Versions are managed entirely on the TeamCity side — do not set <Version> in .csproj files.

At publish time, the TC HrynCo / HrynCo.EF / publish build:

  1. Writes the current build number into Directory.Build.props as <Version>%build.number%</Version>.
  2. Builds and packs both projects.
  3. Pushes the resulting .nupkg files to nuget.org.

The build number follows the pattern 1.0.<counter> (e.g. 1.0.6, 1.0.7, …). The counter increments automatically on each successful publish run. To release a new version, merge to main — the publish build triggers automatically.

To bump the major or minor version, update the build number pattern in TC: HrynCo → HrynCo.EF → publish → Edit Configuration → General → Build number format.

Class diagram

classDiagram
    namespace HrynCo_DAL_Abstract {
        class IEntity {
            <<interface>>
            +object Id
            +DateTimeOffset Created
            +DateTimeOffset? Updated
        }
        class IEntityTId {
            <<interface>>
            +TId Id
        }
        class EntityTId {
            <<abstract>>
            +TId Id
            +DateTimeOffset Created
            +DateTimeOffset? Updated
        }
        class Entity {
            <<abstract>>
            +Guid Id
        }
        class NamedEntity {
            <<abstract>>
            +string Name
        }
        class IUnitOfWork {
            <<interface>>
            +BeginTransactionAsync() Task~ITransaction~
            +GetCurrentTransaction() ITransaction?
            +ExecuteInTransactionAsync(action) Task
            +ExecuteInTransactionAsync~TResult~(action) Task~TResult~
        }
        class ITransaction {
            <<interface>>
            +CommitAsync() Task
            +RollbackAsync() Task
            +DisposeAsync() ValueTask
        }
        class PagedResultT {
            <<sealed>>
            +IReadOnlyList~T~ Items
            +int Page
            +int PageSize
            +int TotalCount
        }
    }

    namespace HrynCo_DAL_EF {
        class IEfRepository {
            <<interface>>
            +ClearChangeTracker()
        }
        class IEfRepositoryTEntityTId {
            <<interface>>
            +Add(entity) TEntity
            +AddAsync(entity) Task~TEntity~
            +Delete(id)
            +DeleteAsync(id) Task
            +Get(filter, orderBy, includes) IQueryable~TEntity~
            +GetAll() IQueryable~TEntity~
            +GetAllAsync() Task~List~TEntity~~
            +GetById(id) TEntity?
            +GetByIdAsync(id) Task~TEntity?~
            +Exists(id) Task~bool~
            +UpdateAsync(entity) Task
            +SaveChangesAsync() Task
        }
        class IEfRepositoryTEntity {
            <<interface>>
        }
        class BaseEfRepositoryTDbContextTEntityTEntityId {
            <<abstract>>
            +TDbContext DbContext
            +Add() TEntity
            +AddAsync() Task~TEntity~
            +Delete()
            +DeleteAsync() Task
            +Get() IQueryable~TEntity~
            +GetAll() IQueryable~TEntity~
            +GetAllAsync() Task~List~TEntity~~
            +GetById() TEntity?
            +GetByIdAsync() Task~TEntity?~
            +Exists() Task~bool~
            +Update()
            +UpdateAsync() Task
            +SaveChangesAsync() Task
            #DoRemove()
        }
        class BaseRepositoryTEfRepositoryTDbContextTEntityTEntityId {
            <<abstract>>
            #EfRepository TEfRepository
            #CreateEfRepository()* TEfRepository
        }
        class EfUnitOfWorkTDbContext {
            +BeginTransactionAsync() Task~ITransaction~
            +GetCurrentTransaction() ITransaction?
            +ExecuteInTransactionAsync() Task
        }
        class EfTransactionAdapter {
            +CommitAsync() Task
            +RollbackAsync() Task
            +DisposeAsync() ValueTask
        }
    }

    IEntityTId --|> IEntity : extends
    EntityTId ..|> IEntityTId : implements
    Entity --|> EntityTId : extends (TId=Guid)
    NamedEntity --|> Entity : extends

    IEfRepositoryTEntityTId --|> IEfRepository : extends
    IEfRepositoryTEntity --|> IEfRepositoryTEntityTId : extends (TId=int)
    BaseEfRepositoryTDbContextTEntityTEntityId ..|> IEfRepositoryTEntityTId : implements
    BaseRepositoryTEfRepositoryTDbContextTEntityTEntityId --> BaseEfRepositoryTDbContextTEntityTEntityId : uses (lazy)

    EfUnitOfWorkTDbContext ..|> IUnitOfWork : implements
    EfTransactionAdapter ..|> ITransaction : implements
    EfUnitOfWorkTDbContext --> EfTransactionAdapter : creates

Packages

HrynCo.DAL.Abstract

Abstract DAL contracts — entities, repository interfaces, unit of work, transactions, and pagination.

Type Description
IEntity / IEntity<TId> Base entity contracts
Entity<TId> / Entity Base entity implementations with auto-generated Id
NamedEntity Entity with a Name property
IRepository<T> Generic async repository interface
IUnitOfWork Unit of work interface with transaction support
ITransaction Async transaction contract
PagedResult<T> Pagination result wrapper

HrynCo.DAL.EF

Entity Framework Core implementations of the abstract contracts.

Type Description
BaseRepository<T> Base repository with common CRUD operations
BaseEfRepository<T> EF Core repository with DbContext access
IEfRepository<T> EF-specific repository interface
EfUnitOfWork EF Core unit of work implementation
EfTransactionAdapter Adapts EF transactions to ITransaction

Usage

Reference HrynCo.DAL.Abstract for contracts only (e.g. in domain/application layers).
Reference HrynCo.DAL.EF for the full EF Core implementation (infrastructure layer).

// 1. Define your entity
public class Product : Entity
{
    public string Name { get; set; } = string.Empty;
}

// 2. Implement your repository
public class ProductRepository : BaseEfRepository<Product>
{
    public ProductRepository(YourDbContext context) : base(context) { }
}

// 3. Register in DI
services.AddScoped<IRepository<Product>, ProductRepository>();
services.AddScoped<IUnitOfWork, EfUnitOfWork<YourDbContext>>();
S
Description
No description provided
Readme 69 KiB
Languages
C# 100%