It's kinda Unit of Work, Repository things, done intuitively in EF AND EF Core.
It’s kinda Unit of Work, Repository things, done intuitively in EF AND EF Core.
You must setting up your DbContext
class first, either by inheriting EfCoreDbContext
(EF Core) or EfDbContext
(EF):
public class MyDbContext : EfCoreDbContext // Inherit from EfDbContext if you are using EF6 or above
{
public DbSet<MyEntity> Entities { get; set; }
}
where MyEntity
must inherit from IEntity
or from base templating class BaseEntity<TEntity>
:
public class MyEntity : BaseEntity<MyEntity>
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
next, define your MyDto
class for mapping from MyEntity
. This MyDto
class must inherit from IDto
, or better from BaseDto<TDto, TValidator>
class:
public class MyDto: BaseDto<MyDto, MyDtoFluentValidator>
{
public int Id { get; set; }
public string Name { get; set; }
}
don’t forget to define you MyDto
validator class, by inheriting BaseFluentValidator<T>
(using FluentValidator
) or BaseValitValidator<T>
(using Valit
):
public class MyDtoFluentValidator: BaseFluentValidator<MyDto>
{
public MyDtoFluentValidator()
{
RuleFor(x => x.Id).NotEmpty();
RuleFor(x => x.Name).NotEmpty();
}
}
(BaseValitValidator<T>
version):
public class MyDtoValitValidator : BaseValitValidator<MyDto>
{
public MyDtoValitValitator()
{
Valitator = ValitRules<MyDto>.Create()
.Ensure(x => x.Id, x => x.IsNonZero())
.Ensure(x => x.Name, x => x.Required())
.CreateValitator();
}
protected override IValitator<MyDto> Valitator { get; }
}
next, create you IMapperProfile
derived class to maps MyEntity
to MyDto
and vice-versa:
public class MyMapperProfile : IMapperProfile
{
public Option<(Type Source, Type Destination)>[] GetBinds()
{
return new Option<(Type Source, Type Destination)>[]
{
(typeof(MyEntity), typeof(MyDto)),
(typeof(MyDto), typeof(MyEntity)),
};
}
}
And, lastly, at your startup class, inject the IMapperService
like so:
// Use AutoMapper if you want to support Value-Object pattern
var mapperSvc = new AutoMapperService(); // Choose between AutoMapperService, BatMapMapperService, or MapsterMapperService
mapperSvc.Initialize<IMapperProfile>(new MyMapperProfile());
DslInjecterGetter.SetBaseMapperService(mapperSvc);
var uow = new EfCoreUnitOfWork(new MyDbContext()); // Or use EfUnitOfWork, if you are using EF6 or above.
DslInjecterGetter.SetBaseUnitOfWork(uow);
It’s quite daunting to setting it up huh? But wait, this is how you can utilize my charming library:
Option<CancellationToken> ctok = CancellationToken.None;
var dto = new MyDto();
var createResult = Create<MyEntity, MyDto, MyCreateInterceptor>.Handle(dto, ctok);
var deleteResult = Delete<MyEntity, MyDto, MyDeleteInterceptor>.Handle(dto, ctok);
var readLookupResult = ReadLookup<MyEntity, MyDto, MyReadLookupInterceptor>.Handle(false, ctok);
var readOneResult = ReadOne<MyEntity, MyDto, MyReadOneInterceptor>.Handle(dto, ctok);
var readPagedResult = ReadPaged<MyEntity, MyDto, MyReadPagedInterceptor>.Handle(1, 1, null, "Bla", ctok);
var updateResult = Update<MyEntity, MyDto, MyUpdateInterceptor>.Handle(dto, ctok);
And if you need transactional DB processing, you would do it like this:
using (var trx = uow.GetDbTransaction<MyDbContext>())
{
try
{
var createResult = Create<MyEntity, MyDto, MyCreateInterceptor>.Handle(dto, ctok);
var deleteResult = Delete<MyEntity, MyDto, MyDeleteInterceptor>.Handle(dto, ctok);
var readLookupResult = ReadLookup<MyEntity, MyDto, MyReadLookupInterceptor>.Handle(false, ctok);
var readOneResult = ReadOne<MyEntity, MyDto, MyReadOneInterceptor>.Handle(dto, ctok);
var readPagedResult = ReadPaged<MyEntity, MyDto, MyReadPagedInterceptor>.Handle(1, 1, null, "Bla", ctok);
var updateResult = Update<MyEntity, MyDto, MyUpdateInterceptor>.Handle(dto, ctok);
trx.Commit();
}
catch (Exception ex)
{
trx.Rollback();
}
}
Yes, of course, you will ask: what MyCreateInterceptor
, MyDeleteInterceptor
, MyReadLookupInterceptor
,
MyReadOneInterceptor
, MyReadOneInterceptor
, MyReadPagedInterceptor
, and MyUpdateInterceptor
are all about. It’s your task to find what they are….