using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Providers
{
///
/// a Base Repository Service Implementation which Use a Repository Patterns Implementatin
/// and provides Data Manipulation Methods using Dtos instead of Entities ...
///
/// it can be use of following Repository Patterns Implementation:
/// >
/// >
/// >
///
///
///
///
public abstract class XBaseRepositoryService : IXBaseRepositoryService
where TEntity : XBaseEntity
where TDto : XBaseEntityDto
{
//
#region Properties ...
///
/// Mapper Instance ...
///
public IMapper Mapper { get; }
///
/// Repository Implementation for Data Manipulations ...
///
public IXBaseRepository Repository { get; }
///
/// Mapping Profile Configuration ...
///
/// this Configuration used for Mapping TEntity to Dto and reverse ...
/// default mapping prepared on Constructing time, other custom maps
/// must handled manually if required ...
///
public MapperConfiguration MapperConfiguration { get; }
#endregion
//
#region Constructor ...
public XBaseRepositoryService(
IXBaseRepository repository,
IEnumerable mapperProfiles = null
)
{
//
Repository = repository;
//
// Preparing Mapping Configurations ...
MapperConfiguration = new MapperConfiguration(cfg =>
{
//
// Add Default Profiles ...
//
// Entity To Dto ...
cfg.CreateMap()
.ForMember(dest => dest.Deleted, opt => opt.Ignore());
cfg.CreateMap, XQueryResult>();
//
// Dto to Entity ...
cfg.CreateMap()
.ForMember(dest => dest.Deleted, opt => opt.Ignore());
cfg.CreateMap, XQueryResult>();
//
// Add Provided Profiles if Provided ...
// if Same Profiles Provided, here resolved ...
if (!mapperProfiles.IsNull() &&
mapperProfiles.HasChild())
{
cfg.AddProfiles(mapperProfiles);
}
});
//
// Make Mapper Instance using prepared Configuration ...
Mapper = MapperConfiguration.CreateMapper();
}
#endregion
//
#region Actions ...
//
#region Add ...
///
/// add a new Dto ...
///
///
///
///
///
public async Task AddAsync(
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
// Validate ...
bool isValid = !item.IsNull();
if (!isValid)
{
return result;
}
//
try
{
//
var entity = Mapper.Map(item);
//
entity = await Repository.AddAsync(
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// add or update a Dto (add if not exists/update if exists) ...
///
///
///
///
///
public async Task AddOrUpdateAsync(
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
// Validate ...
bool isValid = !item.IsNull();
if (!isValid)
{
return result;
}
//
try
{
//
var entity = Mapper.Map(item);
//
entity = await Repository.AddOrUpdateAsync(
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// add a range of new Dtos ...
///
///
///
///
///
public async Task AddRangeAsync(
IEnumerable items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
// Validate ...
bool isValid =
!items.IsNull() &&
items.HasChild();
if (!isValid)
{
return;
}
//
try
{
//
var entities = Mapper.Map>(items);
//
await Repository.AddRangeAsync(
items: entities,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{ }
}
#endregion
//
#region Update ...
///
/// Update an Dto values ...
///
///
///
///
///
///
public async Task UpdateAsync(
TKey id,
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = Mapper.Map(item);
//
entity = await Repository.UpdateAsync(
id: item.Id,
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// Update a range of Dtos ...
///
///
///
///
///
public async Task UpdateRangeAsync(
IEnumerable items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var result =
!items.IsNull() &&
items.HasChild();
if (!result)
{
return result;
}
//
try
{
//
var entitis = Mapper.Map>(items);
//
result = await Repository.UpdateRangeAsync(
items: entitis,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{
result = false;
}
//
return result;
}
#endregion
//
#region Remove ...
///
/// remove an Dto by it's Id ...
///
///
///
///
///
///
public async Task RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = await Repository.RemoveAsync(
id: id,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// remove an Dto ...
///
///
///
///
///
///
public async Task RemoveAsync(
TDto item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = Mapper.Map(item);
//
entity = await Repository.RemoveAsync(
item: entity,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// remove a range of exists Dtos ...
///
///
///
///
///
///
public async Task RemoveRangeAsync(
IEnumerable items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!items.IsNull() &&
items.HasChild();
if (!isValid)
{
return;
}
//
var entities = Mapper.Map>(items);
//
try
{
//
await Repository.RemoveRangeAsync(
items: entities,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{ }
}
#endregion
//
#region Count ...
///
/// count all exists Dtos ...
///
///
///
///
public async Task CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
var result = await Repository.CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return result;
}
///
/// count all exists Entities Pages by providing page size ...
///
///
///
///
///
///
public async Task PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
var result = await Repository.PagesCountAsync(
pageSize: pageSize,
totalItems: totalItems,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return result;
}
#endregion
//
#region Exists ...
///
/// Check a Dto exists or not ...
///
///
///
///
///
public async Task IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
var result = await Repository.IsExistsAsync(
id: id,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return result;
}
#endregion
//
#region Retrieve ...
///
/// retrieve an Dto by it's Id ...
///
///
///
///
///
///
public async Task GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func, IIncludableQueryable> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = await Repository.GetAsync(
id: id,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// retrieve all exists Dtos ...
///
///
///
///
///
///
public async Task> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func, IOrderedQueryable> orderBuilder = null,
Func, IIncludableQueryable> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
IEnumerable result = Enumerable.Empty();
//
try
{
//
var entities = await Repository.GetAllAsync(
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map>(entities);
}
catch
{ }
//
return result;
}
///
/// retrieve all exists Dtos
/// as Async Enumerable ...
///
///
///
///
///
///
public async IAsyncEnumerable GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func, IOrderedQueryable> orderBuilder = null,
Func, IIncludableQueryable> includeBuilder = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
//
var entityEnumerable = Repository.GetAllAsAsyncEnumerable(
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
await foreach (var entity in entityEnumerable)
{
//
if (cancellationToken.IsCancellationRequested)
{
yield break;
}
//
var dto = Mapper.Map(entity);
yield return dto;
}
}
///
/// find an Dto by providing a Conditional Expression ...
///
///
///
///
///
///
public async Task FindOneAsync(
Expression> predicate,
bool ignoreSoftDeleteds = true,
Func, IIncludableQueryable> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = await Repository.FindOneAsync(
predicate: predicate,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map(entity);
}
catch
{ }
//
return result;
}
///
/// find a collection of Dtos by proving a Conditional Expression ...
///
///
///
///
///
///
///
public async Task> FindManyAsync(
Expression> predicate,
bool ignoreSoftDeleteds = true,
Func, IOrderedQueryable> orderBuilder = null,
Func, IIncludableQueryable> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
IEnumerable result = Enumerable.Empty();
//
try
{
//
var entities = await Repository.FindManyAsync(
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map>(entities);
}
catch
{ }
//
return result;
}
///
/// retrieve Dtos based on XQuery Pagination structure ...
///
///
///
///
///
///
///
///
public async Task> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression> predicate = null,
Func, IOrderedQueryable> orderBuilder = null,
Func, IIncludableQueryable> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
XQueryResult result = null;
//
try
{
//
var entityResult = await Repository.QueryAsync(
query: query,
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map>(entityResult);
}
catch
{ }
//
return result;
}
#endregion
public virtual void Dispose()
{ }
#endregion
}
}