Here's a quick start guide for working with the YuckQi.Data
NuGet package.
Begin with a domain model for some entity your application will work with:
public class Cat : EntityBase<Int64>, ICreated
{
public String? FurColor { get; set; }
public String? Name { get; set; }
public Decimal WeightLbs { get; set; }
public DateTime CreationMomentUtc { get; set; }
}
* EntityBase<T>
and ICreated
both come from YuckQi.Domain.
Create a repository interface for working with Cat
entities that supports only the data operations our domain requires. Repositories should be specific to a single domain entity.
public interface ICatRepository
{
Task<Cat> CreateCatAsync(Cat entity);
Task<Cat> GetCatAsync(Int64 key);
}
The implementation for this repository will take abstract data handlers from YuckQi.Data as constructor parameters. The UnitOfWork<T>
is provided to repositories, not services (see below), which allows applications to decide if repositories will have the same UOW scope or not.
public class CatRepository<TScope> : ICatRepository
{
private readonly ICreationHandler<Cat, Int64, TScope> _creator;
private readonly IRetrievalHandler<Cat, Int64, TScope> _retriever;
private readonly IUnitOfWork<TScope> _uow;
public CatRepository(IUnitOfWork<TScope> uow,
ICreationHandler<Cat, Int64, TScope> creator,
IRetrievalHandler<Cat, Int64, TScope> retriever)
{
_uow = uow ?? throw new ArgumentNullException(nameof(uow));
_creator = creator ?? throw new ArgumentNullException(nameof(creator));
_retriever = retriever ?? throw new ArgumentNullException(nameof(retriever));
}
public Task<Cat> CreateCatAsync(Cat entity) => _creator.CreateAsync(entity, _uow.Scope);
public Task<Cat> GetCatAsync(Int64 key) => _retriever.GetAsync(key, _uow.Scope);
}
Repositories are used to compose domain services which span multiple related areas. The Dog
entity is not defined here, but is being used to show how several repositories can be used together.
public interface IAnimalService
{
Task<Result<Cat>> CreateCatAsync(Cat entity);
Task<Result<Dog>> CreateDogAsync(Dog entity);
Task<Result<Cat>> GetCatAsync(Int64 key);
Task<Result<Dog>> GetDogAsync(Int64 key);
}
public class AnimalService : IAnimalService
{
private readonly ICatRepository _cats;
private readonly IDogRepository _dogs;
public AnimalService(ICatRepository cats, IDogRepository dogs)
{
_cats = cats ?? throw new ArgumentNullException(nameof(cats));
_dogs = dogs ?? throw new ArgumentNullException(nameof(dogs));
}
public async Task<Result<Cat>> CreateCatAsync(Cat entity) => new(await _cats.CreateCatAsync(entity));
public async Task<Result<Dog>> CreateDogAsync(Dog entity) => new(await _dogs.CreateDogAsync(entity));
public async Task<Result<Cat>> GetCatAsync(Int64 key) => new(await _cats.GetCatAsync(key));
public async Task<Result<Dog>> GetDogAsync(Int64 key) => new(await _dogs.GetDogAsync(key));
}
* Result<T>
comes from YuckQi.Domain.Validation.