Files
xSaherelmWorkspace/Documents/GeneratedContext/xDashboard-xDataService-20260807_230223.txt
2026-08-08 00:31:18 +03:30

13289 lines
420 KiB
Plaintext

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Configuration\XDataBaseConfiguration.cs
using System.Collections.Generic;
using xDataService.Constants;
namespace xDataService.Configuration
{
/// <summary>
/// Describe a Database ...
/// </summary>
public class XDataBaseConfiguration
{
/// <summary>
/// Provider Type ...
/// </summary>
/// <value></value>
public XDbProviders Provider { get; set; }
/// <summary>
/// Connection String which provide Requires Data to Connect to Db Provider ...
/// </summary>
/// <value></value>
public string ConnectionString { get; set; }
/// <summary>
/// Holds Seeding items ...
/// nameof(TEntity) => TEntity
/// </summary>
public IDictionary<string, List<object>> SeedItems { get; set; } = new Dictionary<string, List<object>>();
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Configuration\XDataServiceConfiguration.cs
using System.Collections.Generic;
using xDataService.Constants;
namespace xDataService.Configuration
{
/// <summary>
/// Represent Configurations of DataService Module ...
/// </summary>
public partial class XDataServiceConfiguration
{
/// <summary>
/// the base path for providing GraphQL ...
/// </summary>
/// <value></value>
public string GraphQLBasePath { get; set; } = "/graphql";
/// <summary>
/// Data Bases Configuration ...
/// </summary>
/// <returns></returns>
public IDictionary<string, XDataBaseConfiguration> Databases { get; set; } = new Dictionary<string, XDataBaseConfiguration>();
/// <summary>
/// Enable Soft Delete Entities or Not ...
/// </summary>
/// <value></value>
public bool EnableSoftDelete { get; set; }
/// <summary>
/// Specified Seeding Mode ...
/// </summary>
public XDbSeedingMode SeedingMode { get; set; } = XDbSeedingMode.None;
/// <summary>
/// Enable Tracking of Entities ...
/// Only Used on EFCore ...
/// </summary>
/// <value></value>
public bool EnableTracking { get; set; } = false;
/// <summary>
/// Enable Logging Details of Errors ...
/// Only Used on EFCore ...
/// </summary>
/// <value></value>
public bool EnableDetailedErrors { get; set; } = false;
/// <summary>
/// Enable Logging Sensitive Data ...
/// Only Used on EFCore ...
/// </summary>
/// <value></value>
public bool EnableSensitiveDataLogging { get; set; } = false;
/// <summary>
/// this is a way to provide Default Pagination Data on XQuery based requests ...
/// </summary>
/// <returns></returns>
public PagingConfiguration PagingConfiguration { get; set; } = new PagingConfiguration();
}
/// <summary>
/// this is a way to provide Default Pagination Data on XQuery based requests ...
/// </summary>
public partial class PagingConfiguration
{
/// <summary>
/// Default Page Size ...
/// </summary>
/// <value></value>
public int DefaultPageSize { get; set; } = XDataServiceConstants.DEFAULT_PAGE_SIZE;
/// <summary>
/// restrict Maximum Page Size ...
/// </summary>
/// <value></value>
public int MaxAvailablePageSize { get; set; } = XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE;
/// <summary>
/// restrice Minimum Page Size ...
/// </summary>
/// <value></value>
public int MinAvailablePageSize { get; set; } = XDataServiceConstants.MIN_AVAILABLE_PAGE_SIZE;
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\ConfigurationNodeNames.cs
namespace xDataService.Constants {
public partial struct ConfigurationNodeNames {
public const string DB_PROVIDER_NODE = "XDBProvider";
public const string DATA_SERVICE_NODE = "DataServiceConfiguration";
public const string DATA_SERVICE_DB_SEED_NODE = "DbSeeder";
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDataServiceConstants.cs
namespace xDataService.Constants {
/// <summary>
/// Default Pagination Values ...
/// </summary>
public partial struct XDataServiceConstants {
public static int DEFAULT_PAGE_SIZE = 50;
public static int MAX_AVAILABLE_PAGE_SIZE = 500;
public static int MIN_AVAILABLE_PAGE_SIZE = 20;
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDbProviders.cs
namespace xDataService.Constants {
/// <summary>
/// Represent Supported DBMS for Managing Data ...
/// </summary>
public enum XDbProviders {
None,
MySQL,
SQLite,
Oracle,
SQLServer,
MongoDB,
}
/// <summary>
/// Represent Supported DBMS for Managing Data ...
/// </summary>
public partial struct ProviderType {
public const string MySQL = "MYSQL";
public const string SQLite = "SQLITE";
public const string Oracle = "ORACLE";
public const string MongoDB = "MONGODB";
public const string SQLServer = "SQLSERVER";
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDbSeedingMode.cs
namespace xDataService.Constants
{
/// <summary>
/// All Seeding Data Mode ...
/// </summary>
public enum XDbSeedingMode
{
/// <summary>
/// No Seed Data ...
/// </summary>
None,
/// <summary>
/// Seed Only New Items ...
/// </summary>
AddIfNotExists,
/// <summary>
/// Seed Force (Add/Update) ...
/// </summary>
AddOrUpdate,
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XRepositoryType.cs
using xExceptions.Attributes;
namespace xDataService.Constants
{
public enum XRepositoryType
{
[StringValue("EF")]
EF,
[StringValue("Mongo")]
Mongo,
[StringValue("InMemory")]
InMemory
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Controllers\XBaseRepositoryController.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
using xDataService.Interfaces;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using System.Threading;
using xCommons.Controllers;
using Microsoft.AspNetCore.Authorization;
namespace xDataService.Controllers
{
/// <summary>
/// an Abstract Controller for Providing Entity Repository Actions Implementatin ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
[AllowAnonymous]
public abstract class XBaseRepositoryController<TEntity, TKey> : XBaseApiV1Controller, IXBaseRepositoryController<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
//
#region Properties ...
public IXBaseRepository<TEntity, TKey> Repository { get; }
public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
#endregion
//
#region Constructor ...
protected XBaseRepositoryController(
ILogger<XBaseRepositoryController<TEntity, TKey>> logger,
XAppConfiguration appConfiguration,
XValidationProvider validationProvider,
IXBaseRepository<TEntity, TKey> repository,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
) : base(
logger,
appConfiguration,
validationProvider
)
{
//
Repository = repository;
DefaultOrderBuilder = defaultOrderBuilder;
DefaultIncludeBuilder = defaultIncludeBuilder;
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// Add Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
public virtual async Task<ActionResult<TEntity>> Add(
[FromBody] TEntity item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
ValidationProvider.NotNull(item);
//
// Get Result ...
var result = await Repository
.AddAsync(
item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Add or Update Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("AddOrUpdate")]
public virtual async Task<ActionResult<TEntity>> AddOrUpdate(
[FromBody] TEntity item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
ValidationProvider.NotNull(item);
//
// Get Result ...
var result = await Repository
.AddOrUpdateAsync(
item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Add a Collection of Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("AddMany")]
public virtual async Task<ActionResult> AddMany(
[FromBody] XBaseRangeRequest<TEntity> request,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
await Repository
.AddRangeAsync(
request.Items,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok();
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Retrieve ...
/// <summary>
/// Get Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id}")]
public virtual async Task<ActionResult<TEntity>> Get(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await Repository
.GetAsync(
id,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Get All Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
public virtual async Task<ActionResult<IEnumerable<TEntity>>> GetAll(
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Get Result ...
var result = await Repository
.GetAllAsync(
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Find Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("FindOne/{query}")]
public virtual async Task<ActionResult<TEntity>> FindOne(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotEmpty(query);
//
// Get Result ...
var result = await Repository
.FindOneAsync(
predicate: t =>
t.PropValuesContains(query),
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Find Many Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("FindMany/{query}")]
public virtual async Task<ActionResult<IEnumerable<TEntity>>> FindMany(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotEmpty(query);
//
// Get Result ...
var result = await Repository
.FindManyAsync(
predicate: t =>
t.PropValuesContains(query),
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Retrieve Items Based on Query Mechanism ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("Query")]
public virtual async Task<ActionResult<XQueryResult<TEntity>>> Query(
[FromQuery] XQuery query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(query);
//
// Get Result ...
var result = await Repository
.QueryAsync(
query: query,
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("{id}")]
public virtual async Task<ActionResult<TEntity>> Update(
[FromRoute] TKey id,
[FromBody] TEntity item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(id, item)
.ValidateGroupAsync();
//
// Get Result ...
var result = await Repository
.UpdateAsync(
id: id,
item: item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Update a Collection of items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("UpdateMany")]
public virtual async Task<ActionResult<bool>> UpdateMany(
[FromBody] XBaseRangeRequest<TEntity> request,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
var result = await Repository
.UpdateRangeAsync(
saveChanges: true,
items: request.Items,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Exists ...
/// <summary>
///Check an Item Exists or not ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id}/IsExists")]
public virtual async Task<ActionResult<bool>> IsExists(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await Repository
.IsExistsAsync(
id: id,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Remove ...
/// <summary>
/// Remove an Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpDelete("{id}")]
public virtual async Task<ActionResult<TEntity>> Remove(
[FromRoute] TKey id,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await Repository
.RemoveAsync(
id: id,
saveChanges: true,
softDelete: softDelete,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Remove Many Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="softDelete"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("RemoveMany")]
public virtual async Task<ActionResult> RemoveMany(
[FromBody] XBaseRangeRequest<TEntity> request,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
await Repository
.RemoveRangeAsync(
saveChanges: true,
items: request.Items,
softDelete: softDelete,
cancellationToken: cancellationToken
);
//
return Ok();
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Controllers\XBaseServiceController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Interfaces;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Controllers
{
/// <summary>
/// an Abstract Controller for Providing Entity Dto Repository Service Actions Implementatin ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TKey"></typeparam>
[AllowAnonymous]
public abstract class XBaseServiceController<TEntity, TDto, TKey> : XBaseApiV1Controller, IXBaseServiceController<TEntity, TDto, TKey>
where TEntity : XBaseEntity<TKey>
where TDto : XBaseEntityDto<TKey>
{
//
#region Properties ...
public IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
#endregion
//
#region Constructor ...
protected XBaseServiceController(
ILogger<XBaseServiceController<TEntity, TDto, TKey>> logger,
XAppConfiguration appConfiguration,
XValidationProvider validationProvider,
IXBaseRepositoryService<TEntity, TDto, TKey> repositoryService,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
) : base(
logger,
appConfiguration,
validationProvider
)
{
//
RepositoryService = repositoryService;
DefaultOrderBuilder = defaultOrderBuilder;
DefaultIncludeBuilder = defaultIncludeBuilder;
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// Add Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
public virtual async Task<ActionResult<TDto>> Add(
[FromBody] TDto item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
ValidationProvider.NotNull(item);
//
// Get Result ...
var result = await RepositoryService
.AddAsync(
item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Add or Update Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("AddOrUpdate")]
public virtual async Task<ActionResult<TDto>> AddOrUpdate(
[FromBody] TDto item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
ValidationProvider.NotNull(item);
//
// Get Result ...
var result = await RepositoryService
.AddOrUpdateAsync(
item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Add a Collection of Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("AddMany")]
public virtual async Task<ActionResult> AddMany(
[FromBody] XBaseRangeRequest<TDto> request,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
await RepositoryService
.AddRangeAsync(
request.Items,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok();
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Retrieve ...
/// <summary>
/// Get Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id}")]
public virtual async Task<ActionResult<TDto>> Get(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await RepositoryService
.GetAsync(
id,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Get All Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Get Result ...
var result = await RepositoryService
.GetAllAsync(
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Find Specified Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("FindOne/{query}")]
public virtual async Task<ActionResult<TDto>> FindOne(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotEmpty(query);
//
// Get Result ...
var result = await RepositoryService
.FindOneAsync(
predicate: t =>
t.PropValuesContains(query),
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Find Many Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("FindMany/{query}")]
public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotEmpty(query);
//
// Get Result ...
var result = await RepositoryService
.FindManyAsync(
predicate: t =>
t.PropValuesContains(query),
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Retrieve Items Based on Query Mechanism ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="useDefaultOrders"></param>
/// <param name="useDefaultIncludes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("Query")]
public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
[FromQuery] XQuery query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(query);
//
// Get Result ...
var result = await RepositoryService
.QueryAsync(
query: query,
orderBuilder: useDefaultOrders
? DefaultOrderBuilder
: null,
includeBuilder: useDefaultIncludes
? DefaultIncludeBuilder
: null,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update Item ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("{id}")]
public virtual async Task<ActionResult<TDto>> Update(
[FromRoute] TKey id,
[FromBody] TDto item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(id, item)
.ValidateGroupAsync();
//
// Get Result ...
var result = await RepositoryService
.UpdateAsync(
id: id,
item: item,
saveChanges: true,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Update a Collection of items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("UpdateMany")]
public virtual async Task<ActionResult<bool>> UpdateMany(
[FromBody] XBaseRangeRequest<TDto> request,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
var result = await RepositoryService
.UpdateRangeAsync(
saveChanges: true,
items: request.Items,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Exists ...
/// <summary>
///Check an Item Exists or not ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id}/IsExists")]
public virtual async Task<ActionResult<bool>> IsExists(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await RepositoryService
.IsExistsAsync(
id: id,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
//
#region Remove ...
/// <summary>
/// Remove an Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpDelete("{id}")]
public virtual async Task<ActionResult<TDto>> Remove(
[FromRoute] TKey id,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
ValidationProvider.NotNull(id);
//
// Get Result ...
var result = await RepositoryService
.RemoveAsync(
id: id,
saveChanges: true,
softDelete: softDelete,
cancellationToken: cancellationToken
);
//
return Ok(result
.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Remove Many Items ...
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <param name="softDelete"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("RemoveMany")]
public virtual async Task<ActionResult> RemoveMany(
[FromBody] XBaseRangeRequest<TDto> request,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(request)
.AddNotZeroChilds(request.Items)
.ValidateGroupAsync();
//
// Get Result ...
await RepositoryService
.RemoveRangeAsync(
saveChanges: true,
items: request.Items,
softDelete: softDelete,
cancellationToken: cancellationToken
);
//
return Ok();
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
#endregion
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Db\XDbContext.cs
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Helpers;
using xDataService.Providers;
namespace xDataService.Db
{
/// <summary>
/// Provide an abstraction layout arround DBContext ...
/// Only Used on EFCore ...
/// </summary>
public abstract class XDbContext : DbContext
{
//
#region Properties ...
private readonly string database;
private readonly XDataServiceConfiguration config;
private readonly string[] dynamicEntityRegisterarsNames;
private readonly XEntityRegisterarHandlerService dynamicEntityHandlers;
#endregion
//
#region Entities ...
//
// Register Default and Base Entities ...
#endregion
//
#region Constructor ...
public XDbContext(
string database,
DbContextOptions options,
XDataServiceConfiguration config,
XEntityRegisterarHandlerService dynamicEntityHandlers,
string[] dynamicEntityRegisterarsNames = null
) : base(options)
{
//
try
{
Database.EnsureCreated();
Database.Migrate();
}
catch { }
//
this.config = config;
this.database = database;
this.dynamicEntityHandlers = dynamicEntityHandlers;
this.dynamicEntityRegisterarsNames = dynamicEntityRegisterarsNames;
//
// Handling DbSets of Dynamic Entities ...
if (!dynamicEntityHandlers.IsNull())
{
//
// Configure XEntityRegisterarHandlerService ...
dynamicEntityHandlers.HandleRegisteredEntities();
//
// Loop through Entity Types ...
foreach (var entityType in dynamicEntityHandlers.GetEntityTypes(dynamicEntityRegisterarsNames))
{
//
try
{
//
// Use reflection to call Set<T>()
var method = typeof(XDbContext)
.GetMethod(nameof(XDbContext.Set), Type.EmptyTypes)
.MakeGenericMethod(entityType);
if (!method.IsNull())
{
method.Invoke(this, null);
}
}
catch { }
}
}
}
#endregion
/// <summary>
/// Extract Current Database Configuration ...
/// </summary>
/// <returns></returns>
public XDataBaseConfiguration GetDatabaseConfiguration()
{
//
XDataBaseConfiguration result =
config.Databases.FirstOrDefault(db => string
.Equals(db.Key, database, StringComparison.InvariantCultureIgnoreCase)).Value;
//
return result;
}
//
#region Overrides ...
//
// Prepare Model Configs ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//
OnXModelCreating(modelBuilder);
//
// Automatically apply all IEntityTypeConfiguration<T> in this assembly
modelBuilder.ApplyConfigurationsFromAssembly(typeof(XDbContext).Assembly);
//
// Check Dynamic Registered Service is Exists or not ...
if (!dynamicEntityHandlers.IsNull())
{
//
// Set Entity of Dynamically Registered Entities ...
foreach (var entityType in dynamicEntityHandlers.GetEntityTypes(dynamicEntityRegisterarsNames))
{
modelBuilder.Entity(entityType);
}
//
// Configure Entity using Provided Registerar ...
dynamicEntityHandlers
.HandleApplyRegisteredEntitiesConfigurations(modelBuilder, dynamicEntityRegisterarsNames);
}
//
// Since this class inherit from Identity Db Context,
// we have to pass this to Building Identity Models ...
base.OnModelCreating(modelBuilder);
}
//
// Prepare Configuring ...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//
if (config.EnableDetailedErrors)
{
optionsBuilder.EnableDetailedErrors();
}
//
if (config.EnableSensitiveDataLogging)
{
optionsBuilder.EnableSensitiveDataLogging();
}
//
if (config.EnableTracking)
{
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll);
}
else
{
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
//
OnXConfiguring(optionsBuilder);
//
base.OnConfiguring(optionsBuilder);
}
#endregion
//
#region Abstracts ...
//
public abstract void OnXModelCreating(ModelBuilder modelBuilder);
//
public abstract void OnXConfiguring(DbContextOptionsBuilder optionsBuilder);
#endregion
//
#region Dynamic DbSet(s) ...
public override DbSet<TEntity> Set<TEntity>()
where TEntity : class
{
return base.Set<TEntity>();
}
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Db\XUnitOfWorks.cs
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Db {
/// <summary>
/// Provide Unit Of Works Design Pattern for Db Transactions ...
/// Only Used on EFCore ...
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public class XUnitOfWorks<TDbContext> : IXUnitOfWorks<TDbContext>
where TDbContext : XDbContext {
public TDbContext DbContext { get; }
public XUnitOfWorks (TDbContext context) {
this.DbContext = context;
}
public DbSet<T> GetDbSet<T, TKey> ()
where T : XBaseEntity<TKey> {
return DbContext.Set<T> ();
}
/// <summary>
/// Save Changes
/// </summary>
public int SaveChanges () {
return DbContext.SaveChanges ();
}
/// <summary>
/// Save Changes Async
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> SaveChangesAsync (
CancellationToken cancellationToken = default
) {
return await DbContext.SaveChangesAsync (cancellationToken);
}
public void Dispose () {
DbContext.Dispose ();
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\DI\XDIHelperExtension.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Extensions;
using xDataService.Helpers;
using xDataService.Models;
using xDataService.Providers;
using xExceptions.Constants;
namespace xDataService.DI
{
public static partial class XDIHelperExtension
{
/// <summary>
/// Retrive XDataService Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XDataServiceConfiguration GetXDataServiceConfiguration(
this IConfiguration source
)
{
//
var xDataServiceConfigSection = source
.GetSection(ConfigurationNodeNames.DATA_SERVICE_NODE);
var result = xDataServiceConfigSection.Get<XDataServiceConfiguration>();
//
// Reading Seeders ...
if (!result.IsNull() &&
result.Databases.HasChild())
{
//
result
.Databases
.ToList()
.ForEach(db =>
{
//
var seedItemsSectionName = $"{ConfigurationNodeNames.DATA_SERVICE_NODE}:{nameof(XDataServiceConfiguration.Databases)}:{db.Key}:{nameof(XDataBaseConfiguration.SeedItems)}";
var section = source.GetSection(seedItemsSectionName);
var sectionJson = source.GetSectionAsJson(seedItemsSectionName);
var sectionDict = sectionJson.FromJSON<Dictionary<string, List<object>>>();
if (!sectionDict.IsNull() &&
sectionDict.Values.HasChild())
{
//
sectionDict
.Keys
.ToList()
.ForEach(entity =>
{
//
// Setting Values to Result ...
result.Databases[db.Key].SeedItems[entity] = sectionDict[entity];
});
}
});
}
//
return result;
}
/// <summary>
/// Register XDataService Configuration ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
public static void AddXDataServiceConfiguration(
this IServiceCollection source,
IConfiguration configuration
)
{
//
var config = configuration.GetXDataServiceConfiguration();
if (config.IsNullOrDefault())
{
//
Log("Configurations Not Founded ...");
XException.NotFound.Throw();
}
//
source.AddSingleton(config);
}
/// <summary>
/// Register XDataService Configuration ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
public static void AddXDataServiceConfiguration(
this IServiceCollection source,
XDataServiceConfiguration configuration
)
{
//
if (configuration.IsNullOrDefault())
{
//
Log("Configurations Not Founded ...");
XException.NotFound.Throw();
}
//
source.AddSingleton(configuration);
}
/// <summary>
/// Register a Data Base using Descriptor ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
/// <param name="descriptor"></param>
/// <param name="lifeTime"></param>
public static void AddXDatabase(
this IServiceCollection source,
IConfiguration configuration,
XDatabaseDescriptor descriptor,
ServiceLifetime lifeTime = ServiceLifetime.Scoped
)
{
//
// Validate Database Descriptor ...
var isValid =
!descriptor.IsNullOrDefault() &&
!descriptor.Name.IsNullOrEmpty();
if (!isValid)
{
//
Log("Invalid Database Descriptor ...");
return;
}
//
// Check Service Collection Validation ...
isValid =
!source.IsNull() &&
!configuration.IsNull();
if (!isValid)
{
//
Log("Invalid Service Provider or Configuration ...");
return;
}
//
// Get Registere Data Service Configuration ...
var xDataServiceConfiguration = source
.GetRegisteredService<XDataServiceConfiguration>();
isValid = !xDataServiceConfiguration.IsNullOrDefault();
if (!isValid)
{
//
// Extract Configuration from Configuration ...
xDataServiceConfiguration = configuration.GetXDataServiceConfiguration();
isValid = !xDataServiceConfiguration.IsNullOrDefault();
if (!isValid)
{
//
Log("DataService Configuration not provided ...");
return;
}
//
// Register Configuration in DI ...
source.AddSingleton(xDataServiceConfiguration);
}
//
// Check Data Service Configuration has Database ...
isValid =
!xDataServiceConfiguration.Databases.IsNullOrDefault() &&
xDataServiceConfiguration.Databases.HasChild() &&
xDataServiceConfiguration.Databases.Keys.Contains(descriptor.Name);
if (!isValid)
{
//
Log("Invalid Database Descriptor ...");
return;
}
//
// Register Handler Service ...
source.AddSingleton<XEntityRegisterarHandlerService>();
//
// Configure Database Descriptor ...
descriptor.Configure(source);
//
// Register Context ...
if (!descriptor.Context.IsNull() &&
descriptor.Provider != XDbProviders.None &&
!descriptor.ConnectionString.IsNullOrEmpty())
{
//
try
{
//
typeof(XDataServiceHelper).InvokeGenericMethod(
methodName: "AddXDbContext",
runtimeType: descriptor.Context,
args: [
source,
descriptor,
lifeTime
]
);
//
Log($"DbContext: {descriptor.Name} Registered Successfully ...");
}
catch (Exception ex)
{
Log($"DbContext: {descriptor.Name} Registration failed due {ex.Message} ...");
}
}
//
// Register Repositories ...
if (!descriptor.Repositories.IsNull() &&
descriptor.Repositories.HasChild())
{
//
descriptor.Repositories.ToList().ForEach(r =>
{
//
source.AddXRepository(
descriptor: r,
lifeTime: lifeTime
);
});
}
}
public static void AddXRepository(
this IServiceCollection source,
XRepositoryDescriptor descriptor,
ServiceLifetime lifeTime = ServiceLifetime.Scoped
)
{
//
// Preparing Runtime Types ...
Type[] runtimeTypes = descriptor.GetType().GenericTypeArguments;
//
try
{
//
typeof(XDataServiceHelper).InvokeGenericMethod(
methodName: "AddXRepository",
runtimeTypes: runtimeTypes,
args: [
source,
descriptor,
lifeTime
]
);
//
Log($"Repository of: {runtimeTypes[0]}, Registered Successfully ...");
}
catch (Exception ex)
{
Log($"Repository of: {runtimeTypes[0]}, Registration failed due {ex.Message} ...");
}
}
public static void UseXDatabase(
this IApplicationBuilder source,
XDatabaseDescriptor descriptor,
bool isDevelopmentEnvironment = false
)
{
//
// Validate ...
var isValid =
!source.IsNull() &&
descriptor.IsValid();
if (!isValid)
{
//
Log("Invalid Database Configuration ...");
XException.InvalidArgs.Throw();
}
//
// Check Repositories Exists ...
isValid = descriptor.HasRepositories();
if (isValid)
{
//
// Loop through Repositories ...
descriptor.Repositories
.ToList()
.ForEach(r =>
{
//
source.UseXRepository(
descriptor: r,
isDevelopmentEnvironment: isDevelopmentEnvironment
);
});
}
}
/// <summary>
/// Use a Repository Middlewares by Providing it's Descriptor ...
/// </summary>
/// <param name="source"></param>
/// <param name="descriptor"></param>
/// <param name="isDevelopmentEnvironment"></param>
public static void UseXRepository(
this IApplicationBuilder source,
XRepositoryDescriptor descriptor,
bool isDevelopmentEnvironment = false
)
{
//
Log($"Start Using Repository of: {descriptor.Entity}");
//
var withPlayground = false;
if (isDevelopmentEnvironment)
{
withPlayground = true;
}
//
// Create an Scope for Services Acces ...
using (var scope = source.ApplicationServices.CreateScope())
{
//
// Inject XDataServiceConfiguration ForMake Sure DataService Registration ...
var dataServiceConfiguration = scope.ServiceProvider.GetService<XDataServiceConfiguration>();
var isValid = !dataServiceConfiguration.IsNullOrDefault();
if (isValid)
{
//
// Check Seeder Exists ...
// Execute Seeding Data Task if Exists ...
isValid = descriptor.HasSeeder();
if (isValid)
{
//
var seeder = (dynamic)scope.ServiceProvider.GetService(descriptor.SeederService);
isValid = seeder != null;
if (isValid)
{
//
Log($"Start Seeding {descriptor.Entity} ...");
//
// Seeding ...
seeder
.Seed()
.GetAwaiter()
.GetResult();
}
}
//
// Check GraphQL Support ...
isValid = descriptor.HasGraphSupport();
if (isValid)
{
//
// Use WebSockets ...
source.UseWebSockets();
//
// Inject GraphQL Type Helper ...
var helper = (dynamic)scope.ServiceProvider.GetService(descriptor.GraphTypeHelperService);
isValid = helper != null;
if (isValid)
{
//
var graphPath = $"{helper.GetGraphQLPath()}";
var graphBasePath = $"{dataServiceConfiguration.GraphQLBasePath}";
typeof(XDataServiceHelper).InvokeGenericMethod(
methodName: "UseXGraphQL",
runtimeTypes: [
descriptor.Entity,
descriptor.Key,
descriptor.GraphType,
descriptor.GraphTypeKey,
descriptor.GraphQuery,
descriptor.GraphTypeHelperService,
descriptor.GraphTypeHelperImplementation,
descriptor.GraphSchema
],
args: [
source,
graphBasePath,
graphPath,
withPlayground
]
);
//
Log($"Register GraphQL: {graphPath}");
}
}
}
}
}
//
#region Private ...
/// <summary>
/// a LogTag for xDataService ...
/// </summary>
private static string XLogTag = "xDataService";
/// <summary>
/// print a log in Console ...
/// </summary>
/// <param name="message"></param>
private static void Log(string message)
{
Console.WriteLine($"{XLogTag} => {message}");
}
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\DbContextOptionExtensions.cs
using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using MySql.EntityFrameworkCore.Infrastructure;
namespace xDataService.Extensions {
public static class DbContextOptionExtensions {
/// <summary>
/// convert dynamic object to MySqlDbContextOptionBuilder ...
/// Only Used in EFCore ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<MySQLDbContextOptionsBuilder> ToMySQLDbContextOptionsBuilder (
this Action<dynamic> source
) {
return ((Action<MySQLDbContextOptionsBuilder>) source);
}
/// <summary>
/// convert dynamic object to SqliteDbContextOptionBuilder ...
/// Only Used in EFCore ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<SqliteDbContextOptionsBuilder> ToSqliteDbContextOptionsBuilder (
this Action<dynamic> source
) {
return ((Action<SqliteDbContextOptionsBuilder>) source);
}
/// <summary>
/// convert dynamic object to SqlServerDbContextOptionBuilder ...
/// Only Used in EFCore ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<SqlServerDbContextOptionsBuilder> ToSqlServerDbContextOptionsBuilder (
this Action<dynamic> source
) {
return ((Action<SqlServerDbContextOptionsBuilder>) source);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\EntityExtensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using xCommons.Extensions;
using xModels.Base;
namespace xDataService.Extensions {
public static class EntityExtensions {
/// <summary>
/// return all values of an entity properties as a json string ...
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static string GetPropValues<T> (this T item)
where T : XBaseEntity<T> {
//
var props = item.GetType ().GetProperties ();
var vals = props.Select (p => p.GetValue (item));
//
return vals.ToJSON ();
}
/// <summary>
/// check values of all properties of an Entity contains specific value or not ...
/// </summary>
/// <param name="item"></param>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static bool PropValuesContains<T> (this T item, string value)
where T : XBaseEntity<T> => item.GetPropValues ()
.ToNormalString ()
.Contains (value);
/// <summary>
/// Retrieve Default Column Map of specific Entity ...
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IDictionary<string, Expression<Func<T, object>>> GetDefaultColumnsMap<T> (this T item)
where T : XBaseEntity<T> {
//
if (item.IsNull ()) {
return null;
}
//
var result = new Dictionary<string, Expression<Func<T, object>>> ();
var props = item.GetType ().GetProperties ();
//
foreach (var prop in props) {
result.Add (
prop.Name,
t => t.GetType ().GetProperty (prop.Name).GetValue (t, null));
}
//
return result;
}
/// <summary>
/// Check a Type is XBaseEntity or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsXEntity(this Type source)
{
//
var result = !source.IsNull();
if (!result)
{
return result;
}
//
var baseType = source.BaseType;
while(!baseType.IsNull() && baseType != typeof(object))
{
//
if (baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == typeof(XBaseEntity<>))
{
result = true;
break;
}
//
baseType = baseType.BaseType;
}
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\IQueryableExtensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Extensions
{
public static class IQueryableExtensions
{
/// <summary>
/// Apply Search Filter on a Query
/// </summary>
/// <param name="source"></param>
/// <param name="filter"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IQueryable<T> ApplyFilter<T, TKey>(
this IQueryable<T> source,
string filter
)
where T : XBaseEntity<TKey>
{
//
// Apply Filter ...
return source.Where(r => r.PropValuesContains(filter));
}
/// <summary>
/// Apply Search Filter on a Query
/// </summary>
/// <param name="source"></param>
/// <param name="filter"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static async Task<IQueryable<T>> ApplyFilterAsync<T, TKey>(
this IQueryable<T> source,
string filter
)
where T : XBaseEntity<TKey>
{
//
// Where Clause ...
Expression<Func<T, bool>> whereClause = r => r
.PropValuesContains(filter);
//
// Generate Where Function ...
var whereFunc = whereClause.Compile();
//
// Get Enumerable ...
var enumerator = source
.AsAsyncEnumerable();
//
var result = new List<T>();
await
foreach (var entity in enumerator)
{
//
var isApproved = whereFunc(entity);
if (isApproved)
{
result.Add(entity);
}
}
//
return result.AsQueryable();
}
/// <summary>
/// Apply Search Filter on a Enumerable
/// </summary>
/// <param name="source"></param>
/// <param name="filter"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static async Task<IEnumerable<T>> ApplyFilterAsync<T, TKey>(
this IEnumerable<T> source,
string filter
)
where T : XBaseEntity<TKey>
{
//
// Where Clause ...
Expression<Func<T, bool>> whereClause = r => r
.PropValuesContains(filter);
//
// Generate Where Function ...
var whereFunc = whereClause.Compile();
//
// Get Enumerable ...
var enumerator = source
.ToList()
.AsQueryable();
//
var result = new List<T>();
foreach (var entity in enumerator)
{
//
var isApproved = whereFunc(entity);
if (isApproved)
{
result.Add(entity);
}
}
//
return result
.AsEnumerable();
}
/// <summary>
/// Apply Search Filter on a Enumerable
/// </summary>
/// <param name="source"></param>
/// <param name="filter"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> ApplyFilter<T>(
this IEnumerable<T> source,
string filter
)
where T : class
{
//
// Apply Filter ...
return source.Where(r => r.PropValuesContains(filter));
}
/// <summary>
/// provide a way to Order an IQueryable by string FieldName ...
/// </summary>
/// <param name="query"></param>
/// <param name="propertyName"></param>
/// <typeparam name="TSource"></typeparam>
/// <returns></returns>
public static IOrderedQueryable<TSource> OrderBy<TSource>(
this IQueryable<TSource> query,
string propertyName
)
{
//
var entityType = typeof(TSource);
//
// Create x => x.PropName
var propertyInfo = entityType.GetProperty(propertyName);
if (propertyInfo.IsNull())
{
XException.InvalidArgs.Throw();
}
//
ParameterExpression arg = Expression.Parameter(entityType, "x");
MemberExpression property = Expression.Property(arg, propertyName);
var selector = Expression.Lambda(property, new ParameterExpression[] { arg });
//
// Get System.Linq.Queryable.OrderBy() method.
var enumarableType = typeof(System.Linq.Queryable);
var method = enumarableType.GetMethods()
.Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition)
.Where(m =>
{
//
var parameters = m.GetParameters().ToList();
//
// Put more restriction here to ensure selecting the right overload
return parameters.Count == 2; // overload that has 2 parameters
}).Single();
//
// The linq's OrderBy<TSource, TKey> has two generic types, which provided here ...
MethodInfo genericMethod = method
.MakeGenericMethod(entityType, propertyInfo.PropertyType);
/*
Call query.OrderBy(selector), with query and selector: x=> x.PropName
Note that we pass the selector as Expression to the method and we don't compile it.
By doing so EF can extract "order by" columns and generate SQL for it.
*/
var newQuery = (IOrderedQueryable<TSource>)genericMethod
.Invoke(genericMethod, new object[] { query, selector });
//
return newQuery;
}
/// <summary>
/// provide a way to Order an IEnumerable by string FieldName ...
/// </summary>
/// <param name="query"></param>
/// <param name="propertyName"></param>
/// <typeparam name="TSource"></typeparam>
/// <returns></returns>
public static IOrderedEnumerable<TSource> OrderBy<TSource>(
this IEnumerable<TSource> query,
string propertyName
)
{
//
var entityType = typeof(TSource);
var propertyInfo = entityType.GetProperty(propertyName);
if (propertyInfo.IsNull())
{
XException.InvalidArgs.Throw();
}
//
return query.OrderBy(x => propertyInfo.GetValue(x, null));
}
/// <summary>
/// provide a way to Order an IQueryable by string FieldName ...
/// </summary>
/// <param name="query"></param>
/// <param name="propertyName"></param>
/// <typeparam name="TSource"></typeparam>
/// <returns></returns>
public static IOrderedQueryable<TSource> OrderByDescending<TSource>(
this IQueryable<TSource> query,
string propertyName
)
{
//
var entityType = typeof(TSource);
//
// Create x => x.PropName
var propertyInfo = entityType.GetProperty(propertyName);
if (propertyInfo.IsNull())
{
XException.InvalidArgs.Throw();
}
//
ParameterExpression arg = Expression.Parameter(entityType, "x");
MemberExpression property = Expression.Property(arg, propertyName);
var selector = Expression.Lambda(property, new ParameterExpression[] { arg });
//
// Get System.Linq.Queryable.OrderBy() method.
var enumarableType = typeof(System.Linq.Queryable);
var method = enumarableType.GetMethods()
.Where(m => m.Name == "OrderByDescending" && m.IsGenericMethodDefinition)
.Where(m =>
{
//
var parameters = m.GetParameters().ToList();
//
// Put more restriction here to ensure selecting the right overload
return parameters.Count == 2; // overload that has 2 parameters
}).Single();
//
// The linq's OrderBy<TSource, TKey> has two generic types, which provided here ...
MethodInfo genericMethod = method
.MakeGenericMethod(entityType, propertyInfo.PropertyType);
/*
Call query.OrderBy(selector), with query and selector: x=> x.PropName
Note that we pass the selector as Expression to the method and we don't compile it.
By doing so EF can extract "order by" columns and generate SQL for it.
*/
var newQuery = (IOrderedQueryable<TSource>)genericMethod
.Invoke(genericMethod, new object[] { query, selector });
//
return newQuery;
}
/// <summary>
/// provide a way to Order an IEnumerable by string FieldName ...
/// </summary>
/// <param name="query"></param>
/// <param name="propertyName"></param>
/// <typeparam name="TSource"></typeparam>
/// <returns></returns>
public static IOrderedEnumerable<TSource> OrderByDescending<TSource>(
this IEnumerable<TSource> query,
string propertyName
)
{
//
var entityType = typeof(TSource);
var propertyInfo = entityType.GetProperty(propertyName);
if (propertyInfo.IsNull())
{
XException.InvalidArgs.Throw();
}
//
return query.OrderByDescending(x => propertyInfo.GetValue(x, null));
}
/// <summary>
/// Apply Sorting on a query
/// </summary>
/// <param name="source"></param>
/// <param name="sortBy"></param>
/// <param name="isAscending"></param>
/// <param name="columnsMap"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IQueryable<T> ApplySorting<T, TKey>(
this IQueryable<T> source,
string sortBy,
bool isAscending,
IDictionary<string, Expression<Func<T, object>>> columnsMap = null
)
where T : XBaseEntity<TKey>
{
//
if (columnsMap == null)
{
//
columnsMap = source.FirstOrDefault()
.GetDefaultColumnsMap();
//
if (columnsMap == null)
{
return source;
}
}
//
// Validate SortBy ...
var sortByItem = columnsMap.Keys
.FirstOrDefault(p =>
p.ToNormalString() == sortBy.ToNormalString());
if (sortByItem.IsNullOrEmpty())
{
return source;
}
//
// Apply Sorting ...
if (isAscending)
{
return source.OrderBy(sortByItem);
}
else
{
return source.OrderByDescending(sortByItem);
}
}
/// <summary>
/// Apply Sorting on a query
/// </summary>
/// <param name="source"></param>
/// <param name="sortBy"></param>
/// <param name="isAscending"></param>
/// <param name="columnsMap"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> ApplySorting<T, TKey>(
this IEnumerable<T> source,
string sortBy,
bool isAscending,
IDictionary<string, Expression<Func<T, object>>> columnsMap = null
)
where T : XBaseEntity<TKey>
{
//
if (columnsMap == null)
{
//
columnsMap = source.FirstOrDefault()
.GetDefaultColumnsMap();
//
if (columnsMap == null)
{
return source;
}
}
//
// Validate SortBy ...
var sortByItem = columnsMap.Keys
.FirstOrDefault(p =>
p.ToNormalString() == sortBy.ToNormalString());
if (sortByItem.IsNullOrEmpty())
{
return source;
}
//
// Apply Sorting ...
if (isAscending)
{
return source.OrderBy(sortByItem);
}
else
{
return source.OrderByDescending(sortByItem);
}
}
/// <summary>
/// Apply Sorting on a Enumerable
/// </summary>
/// <param name="source"></param>
/// <param name="sortBy"></param>
/// <param name="isAscending"></param>
/// <param name="columnsMap"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> ApplySorting<T>(
this IEnumerable<T> source,
string sortBy,
bool isAscending,
IDictionary<string, Expression<Func<T, object>>> columnsMap = null
)
where T : class
{
//
if (columnsMap == null)
{
//
columnsMap = source.FirstOrDefault()
.GetDefaultColumnsMap();
//
if (columnsMap == null)
{
return source;
}
}
//
// Validate SortBy ...
var sortByItem = columnsMap.Keys
.FirstOrDefault(p =>
p.ToNormalString() == sortBy.ToNormalString());
if (sortByItem.IsNullOrEmpty())
{
return source;
}
//
// Apply Sorting ...
if (isAscending)
{
return source.OrderBy(sortByItem);
}
else
{
return source.OrderByDescending(sortByItem);
}
}
/// <summary>
/// Apply Paging on a qury
/// </summary>
/// <param name="source"></param>
/// <param name="page"></param>
/// <param name="pageSize"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IQueryable<T> ApplyPaging<T>(
this IQueryable<T> source,
int? page,
int? pageSize
)
{
//
if (!page.HasValue ||
page <= 0)
{
page = 1;
}
//
if (!pageSize.HasValue ||
pageSize <= 0 ||
pageSize > XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE)
{
pageSize = XDataServiceConstants.DEFAULT_PAGE_SIZE;
}
//
var pageVal = page.GetValueOrDefault();
var pageSizeVal = pageSize.GetValueOrDefault();
//
return source
.Skip((pageVal - 1) * pageSizeVal)
.Take(pageSizeVal);
}
/// <summary>
/// Apply Paging on a Enumerable
/// </summary>
/// <param name="source"></param>
/// <param name="page"></param>
/// <param name="pageSize"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> ApplyPaging<T>(
this IEnumerable<T> source,
int? page,
int? pageSize
)
{
//
if (!page.HasValue ||
page <= 0)
{
page = 1;
}
//
if (!pageSize.HasValue ||
pageSize <= 0 ||
pageSize > XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE)
{
pageSize = XDataServiceConstants.DEFAULT_PAGE_SIZE;
}
//
var pageVal = page.GetValueOrDefault();
var pageSizeVal = pageSize.GetValueOrDefault();
//
return source
.Skip((pageVal - 1) * pageSizeVal)
.Take(pageSizeVal);
}
/// <summary>
/// Count Query Pages based on Specified Total Number ...
/// </summary>
/// <param name="source"></param>
/// <param name="totalItems"></param>
/// <returns></returns>
public static int CountPages(this XQuery source, int totalItems)
{
//
int result = 0;
//
// Validate and Calculate ...
if (!source.IsNull() && source.PageSize > 0 && totalItems > 0)
{
//
result = totalItems / source.PageSize;
if (totalItems % source.PageSize > 0)
{
result++;
}
}
//
return result;
}
/// <summary>
/// Normalize an XQuery based on Data Service Configurations ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static XQuery NormalizeQuery(
this XQuery source,
XDataServiceConfiguration configuration //
)
{
//
if (source.IsNull())
{
source = new XQuery();
}
//
// Page Size Normalization ...
if (source.PageSize < configuration.PagingConfiguration.MinAvailablePageSize)
{
source.PageSize = configuration.PagingConfiguration.MinAvailablePageSize;
}
if (source.PageSize > configuration.PagingConfiguration.MaxAvailablePageSize)
{
source.PageSize = configuration.PagingConfiguration.MaxAvailablePageSize;
}
//
return source;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XDatabaseDescriptorExtensions.cs
using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Models;
namespace xDataService.Extensions
{
public static class XDatabaseDescriptorExtensions
{
/// <summary>
/// Validate a Database Descriptor ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsValid(this XDatabaseDescriptor source)
{
//
var result =
!source.IsNull() &&
!source.Name.IsNullOrEmpty();
//
return result;
}
/// <summary>
/// Chack a Descriptor Has Provider or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasProvider(this XDatabaseDescriptor source)
{
//
var result =
source.IsValid() &&
source.Provider != XDbProviders.None;
//
return result;
}
/// <summary>
/// Check a Descriptor Has EF Core Context or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasContext(this XDatabaseDescriptor source)
{
//
var result =
source.IsValid() &&
source.HasProvider() &&
source.Provider != XDbProviders.MongoDB &&
!source.Context.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has Repositories or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasRepositories(this XDatabaseDescriptor source)
{
//
var result =
source.IsValid() &&
source.HasProvider() &&
!source.Repositories.IsNull() &&
source.Repositories.HasChild();
//
return result;
}
/// <summary>
/// Check a Descriptor Has MongoDB Convention Packs ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasConventionPacks(this XDatabaseDescriptor source)
{
//
var result =
source.IsValid() &&
source.HasProvider() &&
source.Provider == XDbProviders.MongoDB &&
!source.ConventionPacks.IsNull();
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XDataServiceConfigurationExtensions.cs
using System.Linq;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
namespace xDataService.Extensions {
public static class XDataServiceConfigurationExtensions {
/// <summary>
/// Extract Provider enum from Provider Type ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XDbProviders ToDbProvider (this string source) {
//
if (source.IsNullOrEmpty ()) {
return XDbProviders.None;
}
//
source = source.ToNormalString ();
//
var result = source == ProviderType.MySQL.ToNormalString () ?
XDbProviders.MySQL :
source == ProviderType.SQLite.ToNormalString () ?
XDbProviders.SQLite :
source == ProviderType.SQLServer.ToNormalString () ?
XDbProviders.SQLServer :
source == ProviderType.MongoDB.ToNormalString () ?
XDbProviders.MongoDB :
XDbProviders.None;
//
return result;
}
/// <summary>
/// Retrieve Mongo URI from ConnectionString
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static string GetMongoDbURI (this XDataBaseConfiguration source) {
//
var parts = source.GetConnectionParts ();
var result = parts
.Where (p => p.Trim ().StartsWith ("Uri="))
.FirstOrDefault ();
result = result.Replace ("Uri=", "").Trim ();
//
return result;
}
/// <summary>
/// Retrieve Mongo Database Name from Connaction string
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static string GetMongoDbDatabase (this XDataBaseConfiguration source) {
//
var parts = source.GetConnectionParts ();
var result = parts
.Where (p => p.Trim ().StartsWith ("Database="))
.FirstOrDefault ();
result = result.Replace ("Database=", "").Trim ();
//
return result;
}
//
#region Private ...
private static string[] GetConnectionParts (this XDataBaseConfiguration source) {
//
var result = source.ConnectionString.Split (';');
//
return result;
}
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XGraphQLExtensions.cs
using GraphQL;
using GraphQL.Types;
using xDataService.Constants;
using xModels.Dtos;
namespace xDataService.Extensions {
public static class XGraphQLExtensions {
public static TKey GetIdArgument<TKey> (this IResolveFieldContext<object> source) {
return source.GetArgument<TKey> (XGraphQLHelper.GetIdArgument<IntGraphType>().Name);
}
public static bool GetIgnoreSoftDeletedArgument<T> (this IResolveFieldContext<T> source) {
return source.GetArgument<bool> (XGraphQLHelper.IgnoreSoftDeletedArgument.Name);
}
public static string GetSearchQueryArgument<T> (this IResolveFieldContext<T> source) {
return source.GetArgument<string> (XGraphQLHelper.SearchQueryArgument.Name);
}
public static XQuery GetQueryArgument<T> (this IResolveFieldContext<T> source) {
return source.GetArgument<XQuery> (XGraphQLHelper.QueryArgument.Name);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XMongoDbExtensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Core.Bindings;
using MongoDB.Driver.Core.Clusters;
using MongoDB.Driver.Core.Servers;
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
using MongoDB.Driver.Linq;
using xDataService.Mongo;
namespace xDataService.Extensions {
public static class XMongoDbExtensions {
public static Guid ToGuid (this ObjectId source) {
//
var bytes = source
.ToByteArray ()
.Concat (new byte[] { 5, 5, 5, 5 })
.ToArray ();
//
var result = new Guid (bytes);
//
return result;
}
public static ObjectId ToObjectId (this Guid source) {
//
var bytes = source
.ToByteArray ()
.Take (12)
.ToArray ();
//
var result = new ObjectId (bytes);
//
return result;
}
public static IAsyncEnumerable<T> ToAsyncEnumerable<T> (this IAsyncCursorSource<T> asyncCursorSource) {
return new XAsyncEnumerableAdapter<T> (asyncCursorSource);
}
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T> (this IAsyncCursor<T> source) {
while (await source.MoveNextAsync ()) {
foreach (var current in source.Current) {
yield return current;
}
}
}
public static XMongoAsyncCursor<T> ToAsyncCursor<T> (this IQueryable<T> source) {
return new XMongoAsyncCursor<T> (source);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XReferenceExtensions.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using xCommons.Extensions;
using xDataService.Models;
namespace xDataService.Extensions
{
public static class XReferenceExtensions
{
/// <summary>
/// Converts an XReference<T> to String Representation ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="splitter"></param>
/// <returns></returns>
public static string ToXReferenceString<T>(
this XReference<T> source,
char? splitter = '_'
)
{
//
var result = string.Empty;
//
// Normalize Splitter ...
if (!splitter.HasValue)
{
splitter = '_';
}
//
if (!source.IsNullOrDefault() && source.Index >= 0 && !source.ReferencedTo.IsNull())
{
result = $"{source.ProvidedFor}{splitter.Value}{source.ReferencedTo}{splitter.Value}{source.Index}";
}
//
return result;
}
/// <summary>
/// Parse an String and Extract to XReference<T> if it's Described ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="splitter"></param>
/// <returns></returns>
public static XReference<T> FromXReference<T>(
this string source,
char? splitter = '_'
)
{
//
XReference<T> result = null;
//
// Normalize Splitter ...
if (!splitter.HasValue)
{
splitter = '_';
}
//
if (!source.IsNullOrEmpty())
{
//
var parts = source.Split(splitter.Value);
if (parts.Count() >= 3)
{
//
T referencedTo;
try
{
referencedTo = (T)Convert.ChangeType(parts[1], typeof(T));
} catch
{
referencedTo = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(parts[1]);
}
//
// Parse String Parts ...
result = new XReference<T>
{
ReferencedTo = referencedTo,
Index = (int)Convert.ChangeType(parts[2], typeof(int)),
ProvidedFor = (string)Convert.ChangeType(parts[0], typeof(string)),
};
}
}
//
return result;
}
/// <summary>
/// Converts a Collection of XReference<T> to it's String Representation ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static string ToXReferenceString<T>(this IEnumerable<XReference<T>> source)
{
//
var result = string.Empty;
//
if (!source.IsNull() && source.HasChild())
{
//
var stringList = new List<string>();
foreach (var s in source)
{
//
var sr = ToXReferenceString(s);
if (!sr.IsNullOrEmpty())
{
stringList.Add(sr);
}
}
//
result = stringList.ToListString();
}
//
return result;
}
public static string ToXReferenceString<T>(this ICollection<XReference<T>> source)
{
//
var result = source
.AsEnumerable()
.ToXReferenceString();
//
return result;
}
public static string ToXReferenceString<T>(this IList<XReference<T>> source)
{
//
var result = source
.AsEnumerable()
.ToXReferenceString();
//
return result;
}
/// <summary>
/// Parse an string to XReference<T> Collection Representation ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static IList<XReference<T>> ParseXReferenceList<T>(this string source)
{
//
var result = new List<XReference<T>>();
//
if (!source.IsNullOrEmpty())
{
//
var stringList = source.ParseListString<string>();
if (!stringList.IsNull() && stringList.HasChild())
{
//
foreach (var s in stringList)
{
//
var sr = FromXReference<T>(s);
if (!sr.IsNullOrDefault())
{
result.Add(sr);
}
}
}
}
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XRepositoryDescriptorExtensions.cs
using xCommons.Extensions;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Models;
using xDataService.Providers;
using xModels.Base;
namespace xDataService.Extensions
{
public static class XRepositoryDescriptorExtensions
{
//
#region Hasers ...
/// <summary>
/// Validate a Descriptor ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsValid(this XRepositoryDescriptor source)
{
var result =
!source.IsNull() &&
!source.Key.IsNull() &&
!source.Entity.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has Events Service or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasEvents(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
!source.EventsService.IsNull() &&
!source.EventsImplementation.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has EF Core Context or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasContext(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
!source.Context.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has GraphQL Support or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasGraphSupport(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
source.HasRepository() &&
!source.GraphType.IsNull() &&
!source.GraphQuery.IsNull() &&
!source.GraphSchema.IsNull() &&
!source.GraphTypeKey.IsNull() &&
!source.GraphTypeHelperService.IsNull() &&
!source.GraphTypeHelperImplementation.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has Key Generator Service or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasKeyGenerator(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
!source.KeyGeneratorService.IsNull() &&
!source.KeyGeneratorImplementation.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has Repository Service or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasRepository(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
!source.RepositoryService.IsNull() &&
!source.RepositoryImplementation.IsNull();
//
return result;
}
/// <summary>
/// Check a Descriptor Has Seeder or not ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasSeeder(this XRepositoryDescriptor source)
{
//
var result =
source.IsValid() &&
source.HasRepository() &&
!source.SeederService.IsNull() &&
!source.SeederImplementation.IsNull();
//
return result;
}
#endregion
//
#region Builders ...
public static XRepositoryDescriptor AddEntity<TEntity, TKey>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
{
//
if (source.IsNull())
{
source = new XRepositoryDescriptor();
}
//
source.Key = typeof(TKey);
source.Entity = typeof(TEntity);
//
return source;
}
public static XRepositoryDescriptor AddEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.EventsService = typeof(TEventsService);
source.EventsImplementation = typeof(TEventsImplementation);
//
return source;
}
public static XRepositoryDescriptor AddKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.KeyGeneratorService = typeof(TKeyGeneratorService);
source.KeyGeneratorImplementation = typeof(TKeyGeneratorImplementation);
//
return source;
}
public static XRepositoryDescriptor AddSeeder<TEntity, TKey, TSeederService, TSeederImplementation>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.SeederService = typeof(TSeederService);
source.SeederImplementation = typeof(TSeederImplementation);
//
return source;
}
public static XRepositoryDescriptor AddEFRepository<TEntity, TKey, TContext, TRepositoryService, TRepositoryImplementation>(
this XRepositoryDescriptor source
)
where TContext : XDbContext
where TEntity : XBaseEntity<TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.RepositoryService = typeof(TRepositoryService);
source.RepositoryImplementation = typeof(TRepositoryImplementation);
//
return source;
}
public static XRepositoryDescriptor AddMongoRepository<TEntity, TKey, TRepositoryService, TRepositoryImplementation>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.RepositoryService = typeof(TRepositoryService);
source.RepositoryImplementation = typeof(TRepositoryImplementation);
//
return source;
}
public static XRepositoryDescriptor AddInMemoryRepository<TEntity, TKey, TRepositoryService, TRepositoryImplementation>(
this XRepositoryDescriptor source
)
where TEntity : XBaseEntity<TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
{
//
if (source.IsNull())
{
//
source = new XRepositoryDescriptor();
source = source.AddEntity<TEntity, TKey>();
}
//
source.RepositoryService = typeof(TRepositoryService);
source.RepositoryImplementation = typeof(TRepositoryImplementation);
//
return source;
}
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphObjectType.cs
using GraphQL.Types;
using xModels.Base;
namespace xDataService.GraphQL
{
/// <summary>
/// Base Entity GraphType Object ...
/// </summary>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseGraphObjectType<TEntity, TKey> : ObjectGraphType<TEntity>
where TEntity : XBaseEntity<TKey> {
public XBaseGraphObjectType () {
//
Name = $"{typeof(TEntity).Name}GraphType";
//
Field (x => x.Id);
Field (x => x.Deleted);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLEventType.cs
using GraphQL.Types;
using xDataService.Models;
using xModels.Base;
namespace xDataService.GraphQL {
public class XBaseGraphQLEventType<TEntity, TKey, TGraphType> : ObjectGraphType<XBaseEventModel<TEntity>>
where TGraphType : IGraphType
where TEntity : XBaseEntity<TKey> {
public XBaseGraphQLEventType () {
//
Name = nameof (XBaseGraphQLEventType<TEntity, TKey, TGraphType>);
//
Field (x => x.Model, type : typeof (TGraphType));
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLQuery.cs
using System;
using System.Linq.Expressions;
using GraphQL.Types;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
namespace xDataService.GraphQL
{
public abstract class XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey> : ObjectGraphType, IXBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TEntity : XBaseEntity<TKey>
where TGraph : IGraphType
where TGraphKey : IGraphType
{
//
protected readonly XDataServiceConfiguration configuration;
protected readonly IXBaseRepository<TEntity, TKey> repository;
protected readonly IXBaseGraphQLTypeHelper<TEntity, TKey> helper;
//
public XBaseGraphQLQuery(
XDataServiceConfiguration configuration,
IXBaseRepository<TEntity, TKey> repository,
IXBaseGraphQLTypeHelper<TEntity, TKey> helper
)
{
//
this.helper = helper;
this.repository = repository;
this.configuration = configuration;
//
Name = GetType().Name;
//
#region Retrieve ...
//
// Get ...
FieldAsync<TGraph>(
name: helper.GetInQuerySingleName(),
arguments: new QueryArguments(
XGraphQLHelper.GetIdArgument<TGraphKey>(),
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async context =>
await repository
.GetAsync(
includeBuilder: null,
id: context.GetIdArgument<TKey>(),
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
.ToDynamicObject()
);
//
// GetAll ...
FieldAsync<ListGraphType<TGraph>>(
name: helper.GetInQueryCollectionName(),
arguments: new QueryArguments(
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async context =>
await repository
.GetAllAsync(
orderBuilder: null,
includeBuilder: null,
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
.ToDynamicObject()
);
//
// FindOne ...
FieldAsync<TGraph>(
name: helper.GetFindOneName(),
arguments: new QueryArguments(
XGraphQLHelper.SearchQueryArgument,
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async (context) =>
{
//
var searchQuery = context.GetSearchQueryArgument();
Expression<Func<TEntity, bool>> whereClase = pe => pe
.PropValuesContains(searchQuery);
//
return await repository
.FindOneAsync(
includeBuilder: null,
predicate: whereClase,
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
.ToDynamicObject();
}
);
//
// FindMany ...
FieldAsync<ListGraphType<TGraph>>(
name: helper.GetFindManyName(),
arguments: new QueryArguments(
XGraphQLHelper.SearchQueryArgument,
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async (context) =>
{
//
var searchQuery = context.GetSearchQueryArgument();
Expression<Func<TEntity, bool>> whereClase = pe => pe
.PropValuesContains(searchQuery);
//
return await repository
.FindManyAsync(
orderBuilder: null,
includeBuilder: null,
predicate: whereClase,
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
.ToDynamicObject();
}
);
//
// Query ...
FieldAsync<XGraphQueryResult<TEntity, TGraph>>(
name: helper.GetQueryName(),
arguments: new QueryArguments(
XGraphQLHelper.QueryArgument,
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async context =>
await repository
.QueryAsync(
predicate: null,
orderBuilder: null,
includeBuilder: null,
query: context.GetQueryArgument(),
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
.ToDynamicObject()
);
//
// Count ...
FieldAsync<IntGraphType>(
name: helper.GetCountName(),
arguments: new QueryArguments(
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async context =>
await repository
.CountAsync(
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
);
//
// Exists ...
FieldAsync<BooleanGraphType>(
name: helper.GetExistsName(),
arguments: new QueryArguments(
XGraphQLHelper.GetIdArgument<TGraphKey>(),
XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve: async context =>
await repository.IsExistsAsync(
id: context.GetIdArgument<TKey>(),
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
)
);
#endregion
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLSubscription.cs
using System.Collections.Generic;
using GraphQL.Resolvers;
using GraphQL.Types;
using xCommons.Extensions;
using xDataService.Providers;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
namespace xDataService.GraphQL {
public abstract class XBaseGraphQLSubscription<TEntity, TKey, TGraph> : ObjectGraphType
where TGraph : IGraphType
where TEntity : XBaseEntity<TKey> {
public XBaseGraphQLSubscription (IXBaseRepositoryEvents<TEntity> eventProvider = null) {
//
Name = GetType ().Name;
//
// Check if base repository patter registered ...
if (!eventProvider.IsNull ()) {
//
// Add ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.AddEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
context => context.Source as XBaseEventModel<TEntity>
),
Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
return eventProvider.OnAddObservable;
})
});
//
// Add Many ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.AddManyEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
),
Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
return eventProvider.OnAddManyObservable;
})
});
//
// Update ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.UpdateEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
context => context.Source as XBaseEventModel<TEntity>
),
Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
return eventProvider.OnUpdateObservable;
})
});
//
// Update Mnay ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.UpdateManyEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
),
Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
return eventProvider.OnUpdateManyObservable;
})
});
//
// Remove ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.RemoveEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
context => context.Source as XBaseEventModel<TEntity>
),
Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
return eventProvider.OnRemoveObservable;
})
});
//
// Remove Many ...
AddField (new EventStreamFieldType {
//
Name = nameof (XBaseRepositoryEvents<TEntity>.RemoveManyEvent),
Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
),
Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
return eventProvider.OnRemoveManyObservable;
})
});
}
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLTypeHelper.cs
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.GraphQL
{
public abstract class XBaseGraphQLTypeHelper<TEntity, TKey> : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
//
private readonly XDataServiceConfiguration configuration;
//
protected XBaseGraphQLTypeHelper(
XDataServiceConfiguration configuration = null
)
{
this.configuration = configuration;
}
//
public abstract string GetInQueryCollectionName();
public abstract string GetInQuerySingleName();
//
public string GetFindOneName()
{
return $"find{GetInQuerySingleName().ToNormalString().Capitalize()}";
}
public string GetFindManyName()
{
return $"find{GetInQueryCollectionName().ToNormalString().Capitalize()}";
}
public string GetQueryName()
{
return $"query{GetInQueryCollectionName().ToNormalString().Capitalize()}";
}
public string GetCountName()
{
return $"count{GetInQueryCollectionName().ToNormalString().Capitalize()}";
}
public string GetExistsName()
{
return $"exists{GetInQuerySingleName().ToNormalString().Capitalize()}";
}
public string GetGraphQLPath(string baseGraphPath = null)
{
//
baseGraphPath = baseGraphPath.IsNullOrEmpty() ?
configuration.IsNull() || configuration.GraphQLBasePath.IsNullOrEmpty() ?
"" :
configuration.GraphQLBasePath :
baseGraphPath;
//
var basePath = baseGraphPath
.EndsWith("/") ?
baseGraphPath
.Substring(0, baseGraphPath.Length - 1) :
baseGraphPath;
//
return $"{basePath}/{GetInQueryCollectionName().ToNormalString()}";
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XCursorHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
namespace xDataService.Helpers {
public partial class XCursorHelper {
public static string ToCursor<T> (T id) {
//
// Check Numbers ...
if (id.ToString ().IsDigits ()) {
return Convert
.ToBase64String (BitConverter
.GetBytes (Convert.ToInt32 (id))
);
} else
//
// Check Guid ...
if (id.ToString ().IsGuid ()) {
return Convert
.ToBase64String (new Guid (id.ToString ())
.ToByteArray ());
} else
//
// Assume as String ...
{
return Convert
.ToBase64String (id
.ToString ().ToBytes ());
}
}
public static T FromCursor<T> (string cursor) {
//
// Check Numbers ...
var returnType = typeof (T);
if (returnType == typeof (int) ||
returnType == typeof (long) ||
returnType == typeof (decimal)) {
return Convert.ChangeType ((BitConverter
.ToInt32 (Convert
.FromBase64String (cursor),
0
))
.ToDynamicObject (), returnType);
} else
//
// Check Guid ...
if (returnType == typeof (Guid)) {
return Convert.ChangeType ((new Guid (
Convert.FromBase64String (cursor)
))
.ToDynamicObject (), returnType);
} else
//
// Assume as String ...
{
return Convert.ChangeType ((
Convert.FromBase64String (cursor)
)
.ToDynamicObject (), returnType);
}
}
public static (string firstCursor, string lastCursor) GetFirstAndLastCursor<T> (IEnumerable<T> ids) {
//
if (ids?.Any () != true) {
return (null, null);
}
//
var firstCursor = ToCursor (ids.First ());
var lastCursor = ToCursor (ids.Last ());
//
return (firstCursor, lastCursor);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XDataServiceHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using GraphQL;
using GraphQL.Server;
using GraphQL.Server.Ui.Playground;
using GraphQL.Server.Ui.Voyager;
using GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MySql.EntityFrameworkCore.Extensions;
using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Db;
using xDataService.Extensions;
using xDataService.GraphQL;
using xDataService.Interfaces;
using xDataService.Models;
using xDataService.Providers;
using xExceptions.Constants;
using xModels.Base;
namespace xDataService.Helpers
{
public static class XDataServiceHelper
{
/// <summary>
/// Register DbContext ...
/// </summary>
/// <param name="source"></param>
/// <param name="databaseDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TContext"></typeparam>
public static void AddXDbContext<TContext>(
IServiceCollection source,
XDatabaseDescriptor databaseDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TContext : XDbContext
{
//
var isValid =
databaseDescriptor.IsValid() &&
databaseDescriptor.HasProvider();
if (!isValid)
{
XException.InvalidConfiguration.Throw();
}
//
switch (databaseDescriptor.Provider)
{
//
// MySQL ...
case XDbProviders.MySQL:
//
source.AddEntityFrameworkMySQL();
source.AddDbContext<TContext>(cfg =>
{
//
cfg.UseMySQL(
databaseDescriptor.ConnectionString,
databaseDescriptor.OptionsBuilder
);
}, lifetime);
break;
//
// SQLite ...
case XDbProviders.SQLite:
//
source.AddEntityFrameworkSqlite();
source.AddDbContext<TContext>(cfg =>
{
//
cfg.UseSqlite(
databaseDescriptor.ConnectionString,
databaseDescriptor.OptionsBuilder
);
}, lifetime);
break;
//
// Oracle ...
case XDbProviders.Oracle:
//
source.AddEntityFrameworkOracle();
source.AddDbContext<TContext>(cfg =>
{
//
cfg.UseOracle(
databaseDescriptor.ConnectionString,
databaseDescriptor.OptionsBuilder
);
}, lifetime);
break;
//
// SQLServer ...
case XDbProviders.SQLServer:
//
source.AddEntityFrameworkSqlServer();
source.AddDbContext<TContext>(cfg =>
{
//
cfg.UseSqlServer(
databaseDescriptor.ConnectionString,
databaseDescriptor.OptionsBuilder
);
}, lifetime);
break;
//
// Mongo DB ...
case XDbProviders.MongoDB:
//
#region XBaseEntity Mappers ...
//
// Map ID as BsonId here ...
BsonClassMap.RegisterClassMap<XBaseEntity<Guid>>(cm =>
{
//
cm.AutoMap();
cm.MapIdMember(c => c.Id);
});
BsonClassMap.RegisterClassMap<XBaseEntity<int>>(cm =>
{
//
cm.AutoMap();
cm.MapIdMember(c => c.Id);
});
BsonClassMap.RegisterClassMap<XBaseEntity<long>>(cm =>
{
//
cm.AutoMap();
cm.MapIdMember(c => c.Id);
});
BsonClassMap.RegisterClassMap<XBaseEntity<string>>(cm =>
{
//
cm.AutoMap();
cm.MapIdMember(c => c.Id);
});
#endregion
//
// Check Has Convention Packs ...
isValid = databaseDescriptor.HasConventionPacks();
if (isValid)
{
//
ConventionRegistry.Register(
nameof(
databaseDescriptor.ConventionPacks
),
databaseDescriptor.ConventionPacks,
type => !type.FullName
.IsNullOrEmpty()
);
}
break;
}
//
isValid =
databaseDescriptor.Provider == XDbProviders.MySQL ||
databaseDescriptor.Provider == XDbProviders.SQLite ||
databaseDescriptor.Provider == XDbProviders.Oracle ||
databaseDescriptor.Provider == XDbProviders.SQLServer;
if (isValid)
{
//
AddXUnitOfWorks<TContext>(
source,
lifetime
);
}
}
//
#region Repository ...
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <returns></returns>
public static void AddXRepository<TEntity, TKey>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TEntity : XBaseEntity<TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TEntity : XBaseEntity<TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TEntity : XBaseEntity<TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation
>(
IServiceCollection source,
XInMemoryRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <typeparam name="TSeederService"></typeparam>
/// <typeparam name="TSeederImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TSeederService,
TSeederImplementation
>(
IServiceCollection source,
XInMemoryRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TSeederService, TSeederImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
//
// DbSeeder ...
isValid = repositoryDescriptor.HasSeeder();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.SeederService,
repositoryDescriptor.SeederImplementation,
lifetime
)
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation
>(
IServiceCollection source,
XMongoRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <typeparam name="TSeederService"></typeparam>
/// <typeparam name="TSeederImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TSeederService,
TSeederImplementation
>(
IServiceCollection source,
XMongoRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TSeederService, TSeederImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
//
// DbSeeder ...
isValid = repositoryDescriptor.HasSeeder();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.SeederService,
repositoryDescriptor.SeederImplementation,
lifetime
)
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <typeparam name="TContext"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TContext
>(
IServiceCollection source,
XEFRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TContext> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TContext : XDbContext
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
}
/// <summary>
/// Register Repository ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <typeparam name="TRepositoryService"></typeparam>
/// <typeparam name="TRepositoryImplementation"></typeparam>
/// <typeparam name="TContext"></typeparam>
/// <typeparam name="TSeederService"></typeparam>
/// <typeparam name="TSeederImplementation"></typeparam>
/// <returns></returns>
public static void AddXRepository<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TContext,
TSeederService,
TSeederImplementation
>(
IServiceCollection source,
XEFRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TContext, TSeederService, TSeederImplementation> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TContext : XDbContext
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
var isValid = repositoryDescriptor.IsValid();
if (!isValid)
{
return;
}
//
// Register KeyGenerator ...
isValid = repositoryDescriptor.HasKeyGenerator();
if (isValid)
{
//
AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Events ...
isValid = repositoryDescriptor.HasEvents();
if (isValid)
{
//
AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Graph ...
isValid = repositoryDescriptor.HasGraphSupport();
if (isValid)
{
//
AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
source,
repositoryDescriptor,
lifetime
);
}
//
// Register Repository ...
isValid = repositoryDescriptor.HasRepository();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.RepositoryService,
repositoryDescriptor.RepositoryImplementation,
lifetime
)
);
}
//
// DbSeeder ...
isValid = repositoryDescriptor.HasSeeder();
if (isValid)
{
//
source.Add(
new ServiceDescriptor(
repositoryDescriptor.SeederService,
repositoryDescriptor.SeederImplementation,
lifetime
)
);
}
}
/// <summary>
/// Use GraphQL ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <param name="source"></param>
/// <param name="graphBasePath"></param>
/// <param name="graphPath"></param>
/// <param name="withPlayGround"></param>
/// <param name="options"></param>
public static void UseXGraphQL<
TEntity,
TKey,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>(
IApplicationBuilder source,
string graphBasePath,
string graphPath,
bool withPlayGround = false
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
source.UseGraphQL<TGraphSchema>(graphPath);
source.UseGraphQLWebSockets<TGraphSchema>();
//
if (withPlayGround)
{
//
source.UseGraphQLPlayground(new GraphQLPlaygroundOptions
{
Path = "/ui/playground",
GraphQLEndPoint = graphBasePath
});
//
source.UseGraphQLVoyager(new GraphQLVoyagerOptions
{
Path = "/ui/voyager",
GraphQLEndPoint = graphBasePath
});
}
}
#endregion
//
#region Entity Assembly Detector ...
/// <summary>
/// Extract Assemblies which Contains Entity ...
/// </summary>
/// <returns></returns>
public static List<Assembly> ExtractEntityAssemblies()
{
//
var result = new List<Assembly>();
//
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in allAssemblies)
{
//
try
{
//
bool hasEntity = assembly
.GetExportedTypes()
.Any(t => t.IsXEntity());
if (hasEntity)
{
result.Add(assembly);
}
}
catch { }
}
//
return result;
}
/// <summary>
/// Register All Entities using Model Builder ...
/// </summary>
/// <param name="modelBuilder"></param>
public static void RegisterAllEntities(this ModelBuilder modelBuilder)
{
//
// Extract Entity Container Assemblies ...
var entityAssemblies = ExtractEntityAssemblies();
foreach(var assembly in entityAssemblies)
{
modelBuilder.ApplyConfigurationsFromAssembly(assembly);
}
}
#endregion
//
#region Private ...
/// <summary>
/// Register Unit of Works ...
/// </summary>
/// <param name="source"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TContext"></typeparam>
public static void AddXUnitOfWorks<TContext>(
IServiceCollection source,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TContext : XDbContext
{
//
source.Add(
new ServiceDescriptor(
typeof(IXUnitOfWorks<TContext>),
typeof(XUnitOfWorks<TContext>),
lifetime
)
);
}
/// <summary>
/// Register Key Generator Service ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TKeyGeneratorService"></typeparam>
/// <typeparam name="TKeyGeneratorImplementation"></typeparam>
/// <returns></returns>
public static void AddXKeyGenerator<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TEntity : XBaseEntity<TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
//
// Validate ...
var isValid =
!source.IsNull() &&
!repositoryDescriptor.IsNull() &&
!repositoryDescriptor.KeyGeneratorService.IsNull() &&
!repositoryDescriptor.KeyGeneratorImplementation.IsNull();
if (!isValid)
{
return;
}
//
// Register ...
source.Add(
new ServiceDescriptor(
repositoryDescriptor.KeyGeneratorService,
repositoryDescriptor.KeyGeneratorImplementation,
lifetime
)
);
}
/// <summary>
/// Register Events Service ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TEventsService"></typeparam>
/// <typeparam name="TEventsImplementation"></typeparam>
/// <returns></returns>
public static void AddXEvents<
TEntity,
TKey,
TEventsService,
TEventsImplementation
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TEntity : XBaseEntity<TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
{
//
// Validate ...
var isValid =
!source.IsNull() &&
!repositoryDescriptor.IsNull() &&
!repositoryDescriptor.EventsService.IsNull() &&
!repositoryDescriptor.EventsImplementation.IsNull();
if (!isValid)
{
return;
}
//
// Register ...
source.Add(
new ServiceDescriptor(
repositoryDescriptor.EventsService,
repositoryDescriptor.EventsImplementation,
lifetime
)
);
}
/// <summary>
/// Register GraphQL Service ...
/// </summary>
/// <param name="source"></param>
/// <param name="repositoryDescriptor"></param>
/// <param name="lifetime"></param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TGraph"></typeparam>
/// <typeparam name="TGraphKey"></typeparam>
/// <typeparam name="TGraphQuery"></typeparam>
/// <typeparam name="TGraphTypeHelperService"></typeparam>
/// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
/// <typeparam name="TGraphSchema"></typeparam>
/// <returns></returns>
public static void AddXGraphQL<
TEntity,
TKey,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>(
IServiceCollection source,
XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
//
// Validate ...
var isValid =
!source.IsNull() &&
!repositoryDescriptor.IsNull() &&
!repositoryDescriptor.GraphType.IsNull() &&
!repositoryDescriptor.GraphQuery.IsNull() &&
!repositoryDescriptor.GraphSchema.IsNull() &&
!repositoryDescriptor.GraphTypeKey.IsNull() &&
!repositoryDescriptor.GraphTypeHelperService.IsNull() &&
!repositoryDescriptor.GraphTypeHelperImplementation.IsNull();
if (!isValid)
{
return;
}
//
// Register Graph Type ...
source.Add(
new ServiceDescriptor(
lifetime: lifetime, // ServiceLifetime.Singleton,
serviceType: repositoryDescriptor.GraphType,
implementationType: repositoryDescriptor.GraphType
)
);
//
// Register Graph Events ...
source.Add(
new ServiceDescriptor(
lifetime: lifetime, // ServiceLifetime.Singleton,
serviceType: typeof(XBaseGraphQLEventType<TEntity, TKey, TGraph>),
implementationType: typeof(XBaseGraphQLEventType<TEntity, TKey, TGraph>)
)
);
//
// Register Graph Type Helper ...
source.Add(
new ServiceDescriptor(
lifetime: ServiceLifetime.Singleton,
serviceType: repositoryDescriptor.GraphTypeHelperService,
implementationType: repositoryDescriptor.GraphTypeHelperImplementation
)
);
//
// Register Graph Query ...
source.Add(
new ServiceDescriptor(
lifetime: lifetime,
serviceType: repositoryDescriptor.GraphQuery,
implementationType: repositoryDescriptor.GraphQuery
)
);
//
// Register Graph Schema ...
source.Add(
new ServiceDescriptor(
lifetime: lifetime,
serviceType: repositoryDescriptor.GraphSchema,
implementationType: repositoryDescriptor.GraphSchema
)
);
//
source.AddScoped<IDocumentExecuter, DocumentExecuter>();
//
// Register Graph Type Schema ...
var builder = source.GetRegisteredService<IGraphQLBuilder>();
if (builder.IsNull())
{
//
Action<GraphQLOptions> options = x =>
{
//
x.EnableMetrics = true;
x.UnhandledExceptionDelegate = context =>
{
Console.WriteLine("XGraphQL Error: " + context.OriginalException.Message);
};
};
builder = source.AddGraphQL(options)
.AddNewtonsoftJson(deserializerSettings => { }, serializerSettings => { })
.AddWebSockets()
.AddDataLoader()
.AddGraphTypes(lifetime);
}
builder.AddGraphTypes(
serviceLifetime: lifetime,
typeFromAssembly: repositoryDescriptor.GraphSchema
);
}
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XGraphQLHelper.cs
using GraphQL.Types;
using xDataService.Models;
using xModels.Dtos;
namespace xDataService.Constants {
public static class XGraphQLHelper {
public static QueryArgument<TKey> GetIdArgument<TKey> ()
where TKey : IGraphType {
return new QueryArgument<TKey> {
Name = "id",
Description = "the id of entity, which you want to retrieve ..."
};
}
public static QueryArgument<BooleanGraphType> IgnoreSoftDeletedArgument = new QueryArgument<BooleanGraphType> {
Name = "ignoreSoftDeleteds",
DefaultValue = true,
Description = "determines result should ignore soft deleted items or not ..."
};
public static QueryArgument<StringGraphType> SearchQueryArgument = new QueryArgument<StringGraphType> {
Name = "searchQuery",
Description = "the value which had to looking for ..."
};
public static QueryArgument<XGraphQueryType> QueryArgument = new QueryArgument<XGraphQueryType> {
Name = "query",
DefaultValue = new XQuery (),
Description = "determines query structure info for retrieving data ..."
};
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseDbSeeder.cs
using System.Threading.Tasks;
using xDataService.Configuration;
using xModels.Base;
namespace xDataService.Interfaces
{
/// <summary>
/// Db Seeder used to seed data on Database on startup time ...
/// </summary>
public interface IXBaseDbSeeder<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
/// <summary>
/// Holds Entity Name ...
/// </summary>
string Entity { get; }
/// <summary>
/// Holds Database Name ...
/// </summary>
string Database { get; }
/// <summary>
/// Repository Service for Data Manipulation ...
/// </summary>
IXBaseRepository<TEntity, TKey> Repository { get; }
/// <summary>
/// DataServiceConfiguration ...
/// </summary>
XDataServiceConfiguration DataServiceConfiguration { get; }
/// <summary>
/// do all seeding action by helping of Repositories here ...
/// </summary>
/// <returns></returns>
Task Seed();
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseGraphQLQuery.cs
using GraphQL.Types;
using xModels.Base;
namespace xDataService.Interfaces
{
public interface IXBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TEntity : XBaseEntity<TKey>
where TGraph : IGraphType
where TGraphKey : IGraphType
{ }
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseGraphQLTypeHelper.cs
using xModels.Base;
namespace xDataService.Interfaces
{
public interface IXBaseGraphQLTypeHelper<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
string GetInQuerySingleName();
string GetInQueryCollectionName();
string GetFindOneName();
string GetFindManyName();
string GetQueryName();
string GetCountName();
string GetExistsName();
string GetGraphQLPath(string baseGraphPath = null);
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseReferencedProvider.cs
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xDataService.Models;
using xModels.Dtos;
namespace xDataService.Interfaces
{
/// <summary>
/// in Some Cases we have Entities Which Can Referenced for Specified
/// Provider and Types ...
/// this interface Globaly introduce all available Actions for those ...
///
/// TKey: type of Provider Models Keys ...
/// TModel: type of Dto which Referenced ...
/// </summary>
public interface IXBaseReferencedProvider<TModel, TKey>
{
//
#region Props ...
/// <summary>
/// Provider Identifier ...
/// </summary>
string Provider { get; }
#endregion
//
#region Referenced Actions ...
/// <summary>
/// Get Specified Indexed Reference for Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="forIndex"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TModel> GetReference(
TKey providedForId,
int forIndex = 0,
CancellationToken cancellationToken = default
);
/// <summary>
/// Retrieve all Exists References of Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<TModel>> GetAllReferences(
TKey providedForId,
CancellationToken cancellationToken = default
);
/// <summary>
/// Extract all Referencing Models for Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
TKey providedForId,
CancellationToken cancellationToken = default
);
/// <summary>
/// Count References ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> CountReferences(
TKey providedForId,
CancellationToken cancellationToken = default
);
/// <summary>
/// Retrieve References of Specific Provided ID as Query ...
/// </summary>
/// <param name="query"></param>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<TModel>> QueryReferences(
XQuery query,
TKey providedForId,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Reference a Model to Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> AddReference(
TModel model,
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Reference a Model to Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> AddReference(
TModel model,
XReference<TKey> reference,
string connectionId = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Reference a Model for Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> RemoveReference(
TModel model,
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Reference a Model for Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> RemoveReference(
TModel model,
XReference<TKey> reference,
string connectionId = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove All References to Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> RemoveReferences(
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
);
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepository.cs
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 Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Interfaces
{
public interface IXBaseRepository : IDisposable { }
/// <summary>
/// Base Repository Pattern Contracts in XDashboard's Data Service ...
/// use for Data Manipulation ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IXBaseRepository<T, TKey> : IXBaseRepository
where T : XBaseEntity<TKey>
{
//
#region Add ...
/// <summary>
/// add a new Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> AddAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// add or update an Entity (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> AddOrUpdateAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// add a range of new Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task AddRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Update ...
/// <summary>
/// Update an Entity values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> UpdateAsync(
TKey id,
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// Update a range of Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> UpdateRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Remove ...
/// <summary>
/// remove an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// remove an Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> RemoveAsync(
T item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// remove a range of exists Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task RemoveRangeAsync(
IEnumerable<T> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Count ...
/// <summary>
/// count all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve whole items as queryable ...
/// </summary>
/// <param name="asNoTracking">a flag for Tracking behaviour</param>
/// <param name="predicate">an Expression for Filter Items ...</param>
/// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
/// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
/// <returns></returns>
IQueryable<T> AsQueryable(
bool asNoTracking = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
);
/// <summary>
/// retrieve an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve all exists Entities
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <returns></returns>
IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
);
/// <summary>
/// find an Entity by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> FindOneAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// find a collection of Entities by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<T>> FindManyAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve Entities based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<T>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
#endregion
//
#region Exists ...
/// <summary>
/// Check an Entity exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Unit Of Work ...
/// <summary>
/// Save all unsaved Transactions on DbContext ...
/// used fo Unit Of Works Design Pattern ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default
);
#endregion
//
#region Key ...
/// <summary>
/// Retrieve Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
TKey GetKey(T item);
/// <summary>
/// Set Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="id"></param>
void SetKey(
ref T item,
TKey id
);
/// <summary>
/// Handle Checking Key ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<T> HandleKeyAsync(
T item,
CancellationToken cancellationToken = default
);
#endregion
//
#region Detach ...
/// <summary>
/// Detach an Entity ...
/// </summary>
/// <param name="item"></param>
void Detach(T item);
/// <summary>
/// Detach an Enumerable of Entities ...
/// </summary>
/// <param name="items"></param>
void Detach(IEnumerable<T> items);
/// <summary>
/// Detach a Query Result of Entity ...
/// </summary>
/// <param name="query"></param>
void Detach(XQueryResult<T> query);
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Interfaces
{
/// <summary>
/// an Interface for Base Repository Actions Providing Using Controllers ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IXBaseRepositoryController<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
//
IXBaseRepository<TEntity, TKey> Repository { get; }
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
//
#region Add ...
Task<ActionResult<TEntity>> Add(
[FromBody] TEntity item,
CancellationToken cancellationToken = default
);
Task<ActionResult<TEntity>> AddOrUpdate(
[FromBody] TEntity item,
CancellationToken cancellationToken = default
);
Task<ActionResult> AddMany(
[FromBody] XBaseRangeRequest<TEntity> request,
CancellationToken cancellationToken = default
);
#endregion
//
#region Retrieve ...
Task<ActionResult<TEntity>> Get(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<IEnumerable<TEntity>>> GetAll(
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<TEntity>> FindOne(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<IEnumerable<TEntity>>> FindMany(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<XQueryResult<TEntity>>> Query(
[FromQuery] XQuery query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
#endregion
//
#region Update ...
Task<ActionResult<TEntity>> Update(
[FromRoute] TKey id,
[FromBody] TEntity item,
CancellationToken cancellationToken = default
);
Task<ActionResult<bool>> UpdateMany(
[FromBody] XBaseRangeRequest<TEntity> request,
CancellationToken cancellationToken = default
);
#endregion
//
#region Exists ...
Task<ActionResult<bool>> IsExists(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Remove ...
Task<ActionResult<TEntity>> Remove(
[FromRoute] TKey id,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
);
Task<ActionResult> RemoveMany(
[FromBody] XBaseRangeRequest<TEntity> request,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
);
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryEvents.cs
using System;
using System.Collections.Generic;
using xDataService.Models;
namespace xDataService.Interfaces {
public interface IXBaseRepositoryEvents<T> {
//
void AddEvent (XBaseEventModel<T> model);
void UpdateEvent (XBaseEventModel<T> model);
void RemoveEvent (XBaseEventModel<T> model);
//
void AddManyEvent (XBaseEventModel<IEnumerable<T>> model);
void UpdateManyEvent (XBaseEventModel<IEnumerable<T>> model);
void RemoveManyEvent (XBaseEventModel<IEnumerable<T>> model);
//
IObservable<XBaseEventModel<T>> OnAddObservable { get; }
IObservable<XBaseEventModel<T>> OnUpdateObservable { get; }
IObservable<XBaseEventModel<T>> OnRemoveObservable { get; }
//
IObservable<XBaseEventModel<IEnumerable<T>>> OnAddManyObservable { get; }
IObservable<XBaseEventModel<IEnumerable<T>>> OnUpdateManyObservable { get; }
IObservable<XBaseEventModel<IEnumerable<T>>> OnRemoveManyObservable { get; }
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryService.cs
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 xModels.Base;
using xModels.Dtos;
namespace xDataService.Interfaces
{
/// <summary>
/// an Interface for Manipulating Data Using Services based on Dto Mapping ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IXBaseRepositoryService<TEntity, TDto, TKey> : IDisposable
where TEntity : XBaseEntity<TKey>
where TDto : XBaseEntityDto<TKey>
{
//
#region Properties ...
/// <summary>
/// Mapper Instance ...
/// </summary>
IMapper Mapper { get; }
/// <summary>
/// Repository Implementation for Data Manipulations ...
/// </summary>
IXBaseRepository<TEntity, TKey> Repository { get; }
/// <summary>
/// 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 ...
/// </summary>
MapperConfiguration MapperConfiguration { get; }
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// add a new Dto ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> AddAsync(
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// add or update a Dto (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> AddOrUpdateAsync(
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// add a range of new Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task AddRangeAsync(
IEnumerable<TDto> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Update ...
/// <summary>
/// Update an Dto values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> UpdateAsync(
TKey id,
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// Update a range of Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> UpdateRangeAsync(
IEnumerable<TDto> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Remove ...
/// <summary>
/// remove an Dto by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// remove an Dto ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> RemoveAsync(
TDto item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// remove a range of exists Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task RemoveRangeAsync(
IEnumerable<TDto> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Count ...
/// <summary>
/// count all exists Dtos ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve an Dto by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve all exists Dtos ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<TDto>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve all exists Dtos
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// find an Dto by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<TDto> FindOneAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// find a collection of Dtos by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<TDto>> FindManyAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// retrieve Dtos based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<TDto>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<TEntity, bool>> predicate = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
);
#endregion
//
#region Exists ...
/// <summary>
/// Check a Dto exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
);
#endregion
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseServiceController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Interfaces
{
/// <summary>
/// an Interface for Base RepositoryService Actions Providing Using Controllers ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IXBaseServiceController<TEntity, TDto, TKey>
where TEntity : XBaseEntity<TKey>
where TDto : XBaseEntityDto<TKey>
{
//
IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
//
#region Add ...
Task<ActionResult<TDto>> Add(
TDto item,
CancellationToken cancellationToken = default
);
Task<ActionResult<TDto>> AddOrUpdate(
TDto item,
CancellationToken cancellationToken = default
);
Task<ActionResult> AddMany(
XBaseRangeRequest<TDto> request,
CancellationToken cancellationToken = default
);
#endregion
//
#region Retrieve ...
Task<ActionResult<TDto>> Get(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<IEnumerable<TDto>>> GetAll(
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<TDto>> FindOne(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<IEnumerable<TDto>>> FindMany(
[FromRoute] string query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
Task<ActionResult<XQueryResult<TDto>>> Query(
[FromQuery] XQuery query,
[FromQuery] bool ignoreSoftDeleteds = true,
[FromQuery] bool useDefaultOrders = false,
[FromQuery] bool useDefaultIncludes = false,
CancellationToken cancellationToken = default
);
#endregion
//
#region Update ...
Task<ActionResult<TDto>> Update(
[FromRoute] TKey id,
[FromBody] TDto item,
CancellationToken cancellationToken = default
);
Task<ActionResult<bool>> UpdateMany(
[FromBody] XBaseRangeRequest<TDto> request,
CancellationToken cancellationToken = default
);
#endregion
//
#region Exists ...
Task<ActionResult<bool>> IsExists(
[FromRoute] TKey id,
[FromQuery] bool ignoreSoftDeletedss = true,
CancellationToken cancellationToken = default
);
#endregion
//
#region Remove ...
Task<ActionResult<TDto>> Remove(
[FromRoute] TKey id,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
);
Task<ActionResult> RemoveMany(
[FromBody] XBaseRangeRequest<TDto> request,
[FromQuery] bool softDelete = true,
CancellationToken cancellationToken = default
);
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXDatabaseDescriptor.cs
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization.Conventions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Db;
using xDataService.Models;
namespace xDataService.Interfaces
{
/// <summary>
/// Data Base Descriptor ...
/// </summary>
public interface IXDatabaseDescriptor
{
//
#region Props ...
/// <summary>
/// Database Name ...
/// </summary>
/// <value></value>
string Name { get; set; }
/// <summary>
/// Database Provider ...
/// </summary>
/// <value></value>
XDbProviders Provider { get; set; }
/// <summary>
/// Db Context Type ...
/// </summary>
/// <value></value>
Type Context { get; set; }
/// <summary>
/// Database Connecion String ...
/// </summary>
/// <value></value>
string ConnectionString { get; set; }
/// <summary>
/// Data Service Configuration ...
/// </summary>
/// <value></value>
XDataBaseConfiguration Configuration { get; set; }
/// <summary>
/// Repositories Descriptions ...
/// </summary>
/// <value></value>
IList<XRepositoryDescriptor> Repositories { get; set; }
/// <summary>
/// Mongo Convention Packs ...
/// </summary>
ConventionPack ConventionPacks { get; set; }
/// <summary>
/// DbContext Options Builder ...
/// </summary>
/// <value></value>
Action<dynamic> OptionsBuilder { get; set; }
#endregion
//
#region Configure ...
/// <summary>
/// Configure Database Descriptor using Registered Services ...
/// </summary>
/// <param name="services"></param>
void Configure(
IServiceCollection services
);
/// <summary>
/// Configure Database Descriptor using IConfiguration ...
/// </summary>
/// <param name="configuration"></param>
void Configure(
IConfiguration configuration
);
/// <summary>
/// Configure Database Descriptor using Database Configuration ...
/// </summary>
/// <param name="configuration"></param>
void Configure(
XDataBaseConfiguration configuration
);
/// <summary>
/// Configure Database Descriptor using Provider and Connection String ...
/// </summary>
/// <param name="provider"></param>
/// <param name="connectionString"></param>
void Configure(
XDbProviders provider,
string connectionString
);
#endregion
}
/// <summary>
/// Data Base Descriptor ...
/// </summary>
/// <typeparam name="TContext"></typeparam>
public interface IXDatabaseDescriptor<TContext> : IXDatabaseDescriptor
where TContext : XDbContext
{ }
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXEntityRegisterar.cs
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using xModels.Base;
namespace xDataService.Interfaces
{
/// <summary>
/// an Interface to Intruduce Entities for Dynamic Registration ...
/// </summary>
public interface IXEntityRegisterar
{
/// <summary>
/// Database Name ...
/// </summary>
string Name { get; }
/// <summary>
/// Returns all entity types this plugin wants registered in the DbContext
/// </summary>
IEnumerable<Type> GetEntityTypes();
/// <summary>
/// Optional: Apply additional per-entity configuration
/// </summary>
void ConfigureEntities(ModelBuilder modelBuilder);
/// <summary>
/// Add XDataService Based Entity to List ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
void AddEntity<TEntity, TKey>()
where TEntity : XBaseEntity<TKey>;
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXKeyGenerator.cs
using System.Threading;
using System.Threading.Tasks;
using xModels.Base;
namespace xDataService.Interfaces
{
/// <summary>
/// Typed Base Key Generator ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IXKeyGenerator<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
bool IsEmpty(TKey id);
Task<TKey> GenerateKey(
IXBaseRepository<TEntity, TKey> repository,
CancellationToken cancellationToken = default
);
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXSequentialGuid.cs
using System;
namespace xDataService.Interfaces {
/// <summary>
/// this service provide Sequential GUID mechanism for Entity Ids ...
/// </summary>
public interface IXSequentialGuid {
Guid GetCurrentGuid ();
Guid Next ();
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXUnitOfWorks.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xDataService.Db;
using xModels.Base;
namespace xDataService.Interfaces {
/// <summary>
/// Provide Unit Of Works Design Pattern for Db Transactions ...
/// Only Used on EFCore ...
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public interface IXUnitOfWorks<TDbContext> : IDisposable
where TDbContext : XDbContext {
TDbContext DbContext { get; }
DbSet<T> GetDbSet<T, TKey> () where T : XBaseEntity<TKey>;
int SaveChanges ();
Task<int> SaveChangesAsync (
CancellationToken cancellationToken = default
);
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XBaseEventModel.cs
namespace xDataService.Models {
/// <summary>
/// Pass Data on Repository Events ...
/// </summary>
/// <typeparam name="T"></typeparam>
public class XBaseEventModel<T> {
public T Model { get; set; }
public XBaseEventModel (T model) {
Model = model;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XDatabaseDescriptor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization.Conventions;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Interfaces;
namespace xDataService.Models
{
/// <summary>
/// Data Base Descriptor ...
/// </summary>
public abstract class XDatabaseDescriptor : IXDatabaseDescriptor
{
//
#region Props ...
/// <summary>
/// Database Name ...
/// </summary>
/// <value></value>
public virtual string Name { get; set; }
/// <summary>
/// Database Provider ...
/// </summary>
/// <value></value>
public virtual XDbProviders Provider { get; set; }
/// <summary>
/// Db Context...
/// </summary>
/// <value></value>
public virtual Type Context { get; set; } = null;
/// <summary>
/// Database Connecion String ...
/// </summary>
/// <value></value>
public virtual string ConnectionString { get; set; }
/// <summary>
/// Data Service Configuration ...
/// </summary>
/// <value></value>
public virtual XDataBaseConfiguration Configuration { get; set; }
/// <summary>
/// Repositories Descriptions ...
/// </summary>
/// <value></value>
public virtual IList<XRepositoryDescriptor> Repositories { get; set; } = null;
/// <summary>
/// Mongo Convention Packs ...
/// </summary>
public ConventionPack ConventionPacks { get; set; } = null;
/// <summary>
/// DbContext Options Builder ...
/// </summary>
/// <value></value>
public Action<dynamic> OptionsBuilder { get; set; } = null;
#endregion
//
#region Constructor ...
/// <summary>
/// Constructor of Descriptor ...
/// </summary>
/// <param name="name"></param>
/// <param name="configuration"></param>
/// <param name="repositories"></param>
public XDatabaseDescriptor(
string name,
IList<XRepositoryDescriptor> repositories = null
)
{
//
Name = name;
Repositories = repositories;
}
#endregion
//
#region Configure ...
/// <summary>
/// Configure Database Descriptor using Registered Services ...
/// </summary>
/// <param name="services"></param>
public void Configure(
IServiceCollection services
)
{
//
bool isValid = !Name.IsNullOrEmpty();
if (!isValid)
{
return;
}
//
var xDataServiceConfiguration = services.GetRegisteredService<XDataServiceConfiguration>();
isValid =
!xDataServiceConfiguration.IsNullOrDefault() &&
xDataServiceConfiguration.Databases.HasChild() &&
xDataServiceConfiguration.Databases.Keys.Any(k => k == Name);
if (!isValid)
{
return;
}
//
var database = xDataServiceConfiguration.Databases[Name];
isValid = !database.IsNullOrDefault();
if (!isValid)
{
return;
}
//
Configure(database);
}
/// <summary>
/// Configure Database Descriptor using IConfiguration ...
/// </summary>
/// <param name="configuration"></param>
public void Configure(
IConfiguration configuration
)
{
//
bool isValid = !Name.IsNullOrEmpty();
if (!isValid)
{
return;
}
//
var xDataServiceConfiguration = configuration.GetXDataServiceConfiguration();
isValid =
!xDataServiceConfiguration.IsNullOrDefault() &&
xDataServiceConfiguration.Databases.HasChild() &&
xDataServiceConfiguration.Databases.Keys.Any(k => k == Name);
if (!isValid)
{
return;
}
//
var database = xDataServiceConfiguration.Databases[Name];
isValid = !database.IsNullOrDefault();
if (!isValid)
{
return;
}
//
Configure(database);
}
/// <summary>
/// Configure Database Descriptor using Database Configuration ...
/// </summary>
/// <param name="configuration"></param>
public void Configure(
XDataBaseConfiguration configuration
)
{
//
Configuration = configuration;
Provider = configuration.Provider;
ConnectionString = configuration.ConnectionString;
}
/// <summary>
/// Configure Database Descriptor using Provider and Connection String ...
/// </summary>
/// <param name="provider"></param>
/// <param name="connectionString"></param>
public void Configure(
XDbProviders provider,
string connectionString
)
{
//
Provider = provider;
ConnectionString = connectionString;
Configuration = new XDataBaseConfiguration
{
Provider = provider,
ConnectionString = connectionString
};
}
#endregion
}
/// <summary>
/// Data Base Descriptor ...
/// </summary>
/// <typeparam name="TContext"></typeparam>
public abstract class XDatabaseDescriptor<TContext> : XDatabaseDescriptor, IXDatabaseDescriptor<TContext>
where TContext : XDbContext
{
/// <summary>
/// Constructor of Descriptor ...
/// </summary>
/// <param name="name"></param>
/// <param name="configuration"></param>
/// <param name="context"></param>
/// <param name="repositories"></param>
public XDatabaseDescriptor(
string name,
IList<XRepositoryDescriptor> repositories = null
) : base(
name: name,
repositories: repositories
)
{
Context = typeof(TContext);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XGraphQueryResult.cs
using GraphQL.Types;
using xModels.Dtos;
namespace xDataService.Models {
public class XGraphQueryResult<TEntity, TGraph> : ObjectGraphType<XQueryResult<TEntity>>
where TGraph : IGraphType {
public XGraphQueryResult () {
//
Name = $"{typeof(TGraph).Name}QueryResult";
//
Field<ListGraphType<TGraph>> (nameof (XQueryResult<TEntity>.Items));
Field (x => x.Page);
Field (x => x.PageSize);
Field (x => x.TotalPages);
Field (x => x.TotalFilteredItems);
Field (x => x.TotalItems);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XGraphQueryType.cs
using GraphQL.Types;
using xModels.Dtos;
namespace xDataService.Models {
public class XGraphQueryType : InputObjectGraphType<XQuery> {
public XGraphQueryType () {
//
Name = "query";
//
Field (x => x.Filter);
Field (x => x.ContainsDetail);
Field (x => x.SortBy);
Field (x => x.IsAscending);
Field (x => x.Page);
Field (x => x.PageSize);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XReference.cs
namespace xDataService.Models
{
public class XReference<T>
{
public int Index { get; set; }
public T ReferencedTo { get; set; }
public string ProvidedFor { get; set; }
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XRepositoryDescriptor.cs
using System;
using GraphQL.Types;
using xDataService.Db;
using xDataService.GraphQL;
using xDataService.Interfaces;
using xDataService.Providers;
using xModels.Base;
namespace xDataService.Models
{
/// <summary>
/// a Global non Generic Repository Descriptor ...
/// </summary>
public class XRepositoryDescriptor
{
/// <summary>
/// Entity Key Type ...
/// </summary>
/// <value></value>
public Type Key { get; set; } = null;
/// <summary>
/// Entity Type ...
/// </summary>
/// <value></value>
public Type Entity { get; set; } = null;
/// <summary>
/// Context Type ...
/// </summary>
/// <value></value>
public Type Context { get; set; } = null;
/// <summary>
/// Graph Type Key ...
/// </summary>
/// <value></value>
public Type GraphTypeKey { get; set; } = null;
/// <summary>
/// Graph Type ...
/// </summary>
/// <value></value>
public Type GraphType { get; set; } = null;
/// <summary>
/// Entity Type GraphQL Schema ...
/// </summary>
/// <value></value>
public Type GraphSchema { get; set; } = null;
/// <summary>
/// Entity GraphQL Type Helper ...
/// </summary>
/// <value></value>
public Type GraphTypeHelperService { get; set; } = null;
/// <summary>
/// Entity GraphQL Type Helper ...
/// </summary>
/// <value></value>
public Type GraphTypeHelperImplementation { get; set; } = null;
/// <summary>
/// Entity GrapQL Query ...
/// </summary>
/// <value></value>
public Type GraphQuery { get; set; } = null;
/// <summary>
/// Repository Event Provider ...
/// </summary>
/// <value></value>
public Type EventsService { get; set; } = null;
/// <summary>
/// Repository Event Provider ...
/// </summary>
/// <value></value>
public Type EventsImplementation { get; set; } = null;
/// <summary>
/// Repository Key Generator for Entity ...
/// </summary>
/// <value></value>
public Type KeyGeneratorService { get; set; } = null;
/// <summary>
/// Repository Key Generator for Entity ...
/// </summary>
/// <value></value>
public Type KeyGeneratorImplementation { get; set; } = null;
/// <summary>
/// Repository Data Access Design Pattern ...
/// </summary>
/// <value></value>
public Type RepositoryService { get; set; } = null;
/// <summary>
/// Repository Data Access Design Pattern ...
/// </summary>
/// <value></value>
public Type RepositoryImplementation { get; set; } = null;
/// <summary>
/// Database Data Seeder ...
/// </summary>
public Type SeederService { get; set; } = null;
/// <summary>
/// Database Data Seeder ...
/// </summary>
public Type SeederImplementation { get; set; } = null;
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public class XRepositoryDescriptor<TEntity, TKey> : XRepositoryDescriptor
where TEntity : XBaseEntity<TKey>
{
public XRepositoryDescriptor() : base()
{
//
Key = typeof(TKey);
Entity = typeof(TEntity);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation
> : XRepositoryDescriptor<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
public XRepositoryDescriptor() : base()
{
//
KeyGeneratorService = typeof(TKeyGeneratorService);
KeyGeneratorImplementation = typeof(TKeyGeneratorImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation
>
where TEntity : XBaseEntity<TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
{
public XRepositoryDescriptor() : base()
{
//
EventsService = typeof(TEventsService);
EventsImplementation = typeof(TEventsImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation
>
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XRepositoryDescriptor() : base()
{
//
GraphType = typeof(TGraph);
GraphTypeKey = typeof(TGraphKey);
GraphQuery = typeof(TGraphQuery);
GraphSchema = typeof(TGraphSchema);
GraphTypeHelperService = typeof(TGraphTypeHelperService);
GraphTypeHelperImplementation = typeof(TGraphTypeHelperImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XInMemoryRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XInMemoryRepositoryDescriptor() : base()
{
//
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XInMemoryRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TSeederService,
TSeederImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XInMemoryRepositoryDescriptor() : base()
{
//
SeederService = typeof(TSeederService);
SeederImplementation = typeof(TSeederImplementation);
//
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XMongoRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XMongoRepositoryDescriptor() : base()
{
//
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XMongoRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TSeederService,
TSeederImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XMongoRepositoryDescriptor() : base()
{
//
SeederService = typeof(TSeederService);
SeederImplementation = typeof(TSeederImplementation);
//
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XEFRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TContext
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TContext : XDbContext
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XEFRepositoryDescriptor() : base()
{
//
Context = typeof(TContext);
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
/// <summary>
/// a Repository Descriptor ...
/// </summary>
public class XEFRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema,
TRepositoryService,
TRepositoryImplementation,
TContext,
TSeederService,
TSeederImplementation
> : XRepositoryDescriptor<
TEntity,
TKey,
TKeyGeneratorService,
TKeyGeneratorImplementation,
TEventsService,
TEventsImplementation,
TGraph,
TGraphKey,
TGraphQuery,
TGraphTypeHelperService,
TGraphTypeHelperImplementation,
TGraphSchema
>
where TGraphSchema : Schema
where TContext : XDbContext
where TGraphKey : IGraphType
where TEntity : XBaseEntity<TKey>
where TGraph : XBaseGraphObjectType<TEntity, TKey>
where TSeederService : IXBaseDbSeeder<TEntity, TKey>
where TEventsService : IXBaseRepositoryEvents<TEntity>
where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
where TRepositoryService : IXBaseRepository<TEntity, TKey>
where TEventsImplementation : XBaseRepositoryEvents<TEntity>
where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
{
public XEFRepositoryDescriptor() : base()
{
//
SeederService = typeof(TSeederService);
SeederImplementation = typeof(TSeederImplementation);
//
Context = typeof(TContext);
RepositoryService = typeof(TRepositoryService);
RepositoryImplementation = typeof(TRepositoryImplementation);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XAsyncEnumerableAdapter.cs
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
namespace xDataService.Mongo {
public class XAsyncEnumerableAdapter<T> : IAsyncEnumerable<T> {
//
private readonly IAsyncCursorSource<T> asyncCursorSource;
//
public XAsyncEnumerableAdapter (IAsyncCursorSource<T> asyncCursorSource) {
this.asyncCursorSource = asyncCursorSource;
}
//
public IAsyncEnumerator<T> GetAsyncEnumerator (CancellationToken cancellationToken) =>
new XAsyncEnumeratorAdapter<T> (asyncCursorSource, cancellationToken);
}
public class XAsyncEnumeratorAdapter<T> : IAsyncEnumerator<T> {
private readonly IAsyncCursorSource<T> asyncCursorSource;
private readonly CancellationToken cancellationToken;
private IAsyncCursor<T> asyncCursor;
private IEnumerator<T> batchEnumerator;
public T Current => batchEnumerator.Current;
public XAsyncEnumeratorAdapter (
IAsyncCursorSource<T> asyncCursorSource,
CancellationToken cancellationToken
) {
//
this.asyncCursorSource = asyncCursorSource;
this.cancellationToken = cancellationToken;
}
public async ValueTask<bool> MoveNextAsync () {
//
if (asyncCursor == null) {
asyncCursor = await asyncCursorSource
.ToCursorAsync (cancellationToken);
}
//
if (batchEnumerator != null &&
batchEnumerator.MoveNext ()) {
return true;
}
//
if (asyncCursor != null &&
await asyncCursor.MoveNextAsync (cancellationToken)) {
//
batchEnumerator?.Dispose ();
batchEnumerator = asyncCursor.Current.GetEnumerator ();
//
return batchEnumerator.MoveNext ();
}
//
return false;
}
public async ValueTask DisposeAsync () {
//
await Task.CompletedTask;
asyncCursor?.Dispose ();
asyncCursor = null;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoAsyncCursor.cs
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
namespace xDataService.Mongo {
public class XMongoAsyncCursor<T> : IAsyncCursor<T> {
public IEnumerable<T> Current { get; }
private IEnumerator<T> CurrentEnumerator { get; }
public XMongoAsyncCursor (IEnumerable<T> source) {
this.Current = source;
this.CurrentEnumerator = source.GetEnumerator ();
}
public void Dispose () {
CurrentEnumerator.Dispose ();
}
public bool MoveNext (CancellationToken cancellationToken = default) {
return CurrentEnumerator.MoveNext ();
}
public Task<bool> MoveNextAsync (CancellationToken cancellationToken = default) {
return Task.Run (
() => CurrentEnumerator.MoveNext (),
cancellationToken : cancellationToken
);
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoQueryable.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xModels.Base;
namespace xDataService.Mongo {
public class XMongoQueryable<TEntity, TKey> : IMongoQueryable<TEntity>
where TEntity : XBaseEntity<TKey> {
private readonly IMongoCollection<TEntity> collection;
public Type ElementType { get; }
public IQueryable<TEntity> Items { get; }
public Expression Expression { get; }
public IQueryProvider Provider { get; }
public XMongoQueryable (
IQueryable<TEntity> items,
IMongoCollection<TEntity> collection
) {
//
this.Items = items;
this.collection = collection;
//
Provider = items.Provider;
Expression = items.Expression;
ElementType = items.ElementType;
}
public IEnumerator<TEntity> GetEnumerator () {
return Items.GetEnumerator ();
}
public QueryableExecutionModel GetExecutionModel () {
return collection.AsQueryable ().GetExecutionModel ();
}
public IAsyncCursor<TEntity> ToCursor (CancellationToken cancellationToken = default) {
return new XMongoAsyncCursor<TEntity> (Items);
}
public Task<IAsyncCursor<TEntity>> ToCursorAsync (CancellationToken cancellationToken = default) {
return Task.Run (() => new XMongoAsyncCursor<TEntity> (Items) as IAsyncCursor<TEntity>);
}
IEnumerator IEnumerable.GetEnumerator () {
return Items.GetEnumerator ();
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoReadPreferenceResolver.cs
using MongoDB.Driver;
namespace xDataService.Mongo {
public static class XMongoReadPreferenceResolver {
public static ReadPreference GetEffectiveReadPreference (
IClientSessionHandle session,
ReadPreference explicitReadPreference,
ReadPreference defaultReadPreference) {
if (explicitReadPreference != null) {
return explicitReadPreference;
}
if (session.IsInTransaction) {
var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference;
if (transactionReadPreference != null) {
return transactionReadPreference;
}
}
return defaultReadPreference ?? ReadPreference.Primary;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseDbSeeder.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
public abstract class XBaseDbSeeder<TEntity, TKey> : IXBaseDbSeeder<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
//
#region Properties ...
/// <summary>
/// Holds Entity Name ...
/// </summary>
public string Entity { get; }
/// <summary>
/// Holds Database Name ...
/// </summary>
public string Database { get; }
/// <summary>
/// Repository Service for Data Manipulation ...
/// </summary>
public IXBaseRepository<TEntity, TKey> Repository { get; }
/// <summary>
/// DataServiceConfiguration ...
/// </summary>
public XDataServiceConfiguration DataServiceConfiguration { get; }
#endregion
//
#region Constructor ...
public XBaseDbSeeder(
string entity,
string database,
IXBaseRepository<TEntity, TKey> repository,
XDataServiceConfiguration dataServiceConfiguration
)
{
//
this.Entity = entity;
this.Database = database;
this.Repository = repository;
this.DataServiceConfiguration = dataServiceConfiguration;
}
#endregion
public async Task Seed()
{
//
// Validate Seed ...
var isValid =
DataServiceConfiguration.SeedingMode != XDbSeedingMode.None &&
DataServiceConfiguration
.Databases
.Any(db =>
db.Key == Database &&
db.Value.SeedItems
.Any(si =>
si.Key == Entity &&
si.Value.HasChild()));
if (!isValid)
{
return;
}
//
// Extract Seeding Items ...
var seedItems = DataServiceConfiguration
.Databases[Database]
.SeedItems[Entity]
.ToList();
foreach (var item in seedItems)
{
//
try
{
//
var entity = item
.ToJSON()
.FromJSON<TEntity>();
//
// Check Item Exists or not ...
var isExist = false;
TEntity exists = null;
var asyncEnumerable = this.Repository.GetAllAsAsyncEnumerable();
await foreach (var e in asyncEnumerable)
{
//
isExist = e.IsSameContent(
dest: entity,
propertyBlackList: new List<string>
{
nameof(entity.Id),
nameof(entity.Deleted)
});
if (isExist)
{
exists = e;
break;
}
}
//
// Seed Based on Seed Mode ...
var seedMode = DataServiceConfiguration.SeedingMode;
switch (seedMode)
{
//
case XDbSeedingMode.AddIfNotExists:
//
if (!isExist)
{
//
exists = await Repository.AddAsync(
item: entity,
saveChanges: true
);
}
break;
//
case XDbSeedingMode.AddOrUpdate:
//
exists = exists.UpdateData(
updateWith: entity,
propertyBlackList: new List<string>
{
nameof(entity.Id),
nameof(entity.Deleted)
}
);
//
await Repository.AddOrUpdateAsync(exists);
break;
}
}
catch
{ }
}
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEFRepository.cs
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 Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Providers
{
/// <summary>
/// a Base Repository Pattern Implementation Specially for EF DBs using
/// EF Core Capabilities ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TDbContext"></typeparam>
public abstract class XBaseEFRepository<T, TKey, TDbContext> : IXBaseRepository<T, TKey>
where T : XBaseEntity<TKey>
where TDbContext : XDbContext
{
//
#region Properties ...
//
public readonly DbSet<T> dbSet;
private readonly IXKeyGenerator<T, TKey> keyGenerator;
public readonly IXUnitOfWorks<TDbContext> unitOfWorks;
public readonly XDataServiceConfiguration configuration;
private readonly IXBaseRepositoryEvents<T> baseRepositoryEvents;
#endregion
//
#region Constructor ...
public XBaseEFRepository(
IXUnitOfWorks<TDbContext> unitOfWorks,
XDataServiceConfiguration configuration,
IXKeyGenerator<T, TKey> keyGenerator = null,
IXBaseRepositoryEvents<T> baseRepositoryEvents = null
)
{
//
this.unitOfWorks = unitOfWorks;
this.keyGenerator = keyGenerator;
this.configuration = configuration;
this.dbSet = unitOfWorks.GetDbSet<T, TKey>();
this.baseRepositoryEvents = baseRepositoryEvents;
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// add a new Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
var entry = await dbSet.AddAsync(
entity: item,
cancellationToken: cancellationToken
);
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<T>(entry.Entity));
}
//
// Return result base on action Succeed ...
return isSucceed ?
entry.Entity :
null;
}
/// <summary>
/// add or update an Entity (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddOrUpdateAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: GetKey(item),
cancellationToken: cancellationToken
);
if (!isExists)
{
//
return await AddAsync(
item: item,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
else
{
//
return await UpdateAsync(
item: item,
id: GetKey(item),
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
}
/// <summary>
/// add a range of new Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Preparing Ids and Keys ...
await dbSet.AddRangeAsync(
await Task
.WhenAll(
items
.Select(async i => await HandleKeyAsync(i))
),
cancellationToken: cancellationToken
);
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update an Entity values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> UpdateAsync(
TKey id,
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Get Exists Entity ...
var existsEntity = await GetAsync(
id: id,
ignoreSoftDeleteds: false,
cancellationToken: cancellationToken
);
//
// Update Data ...
existsEntity.UpdateData(item);
var entry = dbSet.Attach(existsEntity);
entry.State = EntityState.Modified;
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<T>(entry.Entity));
}
//
// Return result base on action Succeed ...
return isSucceed ?
entry.Entity :
null;
}
/// <summary>
/// Update a range of Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> UpdateRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
items
.ToList()
.ForEach(i =>
{
var entry = dbSet.Attach(i);
entry.State = EntityState.Modified;
});
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.UpdateManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
//
// Return result base on action Succeed ...
return isSucceed;
}
#endregion
//
#region Remove ...
/// <summary>
/// remove an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Retrieve Item ...
var item = await GetAsync(
id,
ignoreSoftDeleteds: false,
cancellationToken: cancellationToken
);
if (item.IsNullOrDefault())
{
return null;
}
//
// Handle Remove ...
EntityEntry<T> entry = null;
if (softDelete && configuration.EnableSoftDelete)
{
//
item.Deleted = true;
entry = dbSet.Update(item);
}
else
{
entry = dbSet.Remove(item);
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveEvent(new XBaseEventModel<T>(entry.Entity));
}
//
// Return result base on action Succeed ...
return isSucceed ?
entry.Entity :
null;
}
/// <summary>
/// remove an Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
T item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = await RemoveAsync(
id: item.Id,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// remove a range of exists Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveRangeAsync(
IEnumerable<T> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Handle Remove ...
if (softDelete && configuration.EnableSoftDelete)
{
//
foreach (var item in items)
{
item.Deleted = true;
}
//
dbSet.UpdateRange(items);
}
else
{
dbSet.RemoveRange(items);
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Count ...
/// <summary>
/// count all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
var result = 0;
//
if (ignoreSoftDeleteds)
{
//
result = await dbSet.CountAsync(
predicate: x => !x.Deleted,
cancellationToken: cancellationToken
);
}
else
{
result = await dbSet.CountAsync(cancellationToken);
}
//
return result;
}
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
int pagesCount = count / pageSize;
//
if (count % pageSize > 0)
{
pagesCount++;
}
//
return pagesCount;
}
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve whole items as queryable ...
/// </summary>
/// <param name="asNoTracking">a flag for Tracking behaviour</param>
/// <param name="predicate">an Expression for Filter Items ...</param>
/// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
/// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
/// <returns></returns>
public IQueryable<T> AsQueryable(
bool asNoTracking = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
var result = dbSet
.AsQueryable();
//
// Apply Predicate ...
if (!predicate.IsNull())
{
result = result
.Where(predicate);
}
//
// Apply Includes ...
if (!includeBuilder.IsNull())
{
result = includeBuilder(result);
}
//
// Apply Ordering ...
if (!orderBuilder.IsNull())
{
result = orderBuilder(result);
}
//
return result;
}
/// <summary>
/// retrieve an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = (await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken))
.FirstOrDefault(x => GetKey(x).ToString() == id.ToString());
//
return result;
}
/// <summary>
/// retrieve all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <returns></returns>
public IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.AsAsyncEnumerable();
//
return result;
}
/// <summary>
/// find an Entity by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> FindOneAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = (await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken))
.FirstOrDefault(predicate.Compile());
//
return result;
}
/// <summary>
/// find a collection of Entities by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> FindManyAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = (await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken))
.Where(predicate.Compile());
//
return result;
}
/// <summary>
/// retrieve Entities based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<T>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Normalize Query ...
query = query.NormalizeQuery(configuration);
//
var items = await GetAllAsync();
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Prepare Result ...
var result = new XQueryResult<T>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
//
#region Exists ...
/// <summary>
/// Check an Entity exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = (await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.ToListAsync(cancellationToken))
.Any(predicate: x => GetKey(x).ToString() == id.ToString());
//
return result;
}
#endregion
//
#region Unit Of Work ...
/// <summary>
/// Save all unsaved Transactions on DbContext ...
/// used fo Unit Of Works Design Pattern ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default
)
{
return await unitOfWorks.SaveChangesAsync(cancellationToken);
}
#endregion
//
#region Key ...
/// <summary>
/// Retrieve Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public TKey GetKey(T item)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
//
var keyString = string.Empty;
if (keyProp.IsNull())
{
keyString = string.Empty;
}
else
{
keyString = keyProp.GetValue(item).ToString();
}
//
if (keyString.IsNullOrEmpty())
{
return default(TKey);
}
//
// Prevent Deserializing issues throug JsonReader ...
if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
{
return item.Id;
}
//
return keyString.FromJSON<TKey>();
}
/// <summary>
/// Set Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="id"></param>
public void SetKey(
ref T item,
TKey id
)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
if (keyProp.IsNull())
{
return;
}
//
Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
keyProp.SetValue(item, safeValue, null);
}
/// <summary>
/// Handle Checking Key ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> HandleKeyAsync(
T item,
CancellationToken cancellationToken = default
)
{
//
var keyType = typeof(TKey);
//
// Handle Guid Key Type ...
// Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
if (
(
keyType == typeof(Guid) ||
keyType == typeof(string)
) &&
keyGenerator.IsEmpty(item.Id)
)
{
//
var newKey = await keyGenerator.GenerateKey(this);
//
SetKey(ref item, newKey);
}
//
return item;
}
#endregion
//
#region Detach ...
/// <summary>
/// Detach an Entity ...
/// </summary>
/// <param name="item"></param>
public void Detach(T item)
{
//
if (item.IsNull())
{
return;
}
//
Entry(item).State = EntityState.Detached;
}
/// <summary>
/// Detach an Enumerable of Entities ...
/// </summary>
/// <param name="items"></param>
public void Detach(IEnumerable<T> items)
{
//
if (items.IsNull() || !items.HasChild())
{
return;
}
//
items
.ToList()
.ForEach(item =>
{
Detach(item);
});
}
/// <summary>
/// Detach a Query Result of Entity ...
/// </summary>
/// <param name="query"></param>
public void Detach(XQueryResult<T> query)
{
//
if (query.IsNull() || query.Items.HasChild())
{
return;
}
//
Detach(query.Items);
}
#endregion
#endregion
//
#region Others ...
public void Dispose()
{
unitOfWorks.Dispose();
}
public string GetPropValues(T item)
{
//
var props = item.GetType().GetProperties();
var vals = props.Select(p => p.GetValue(p.Name));
//
return vals.ToJSON();
}
public EntityEntry<T> Entry(T item)
{
return unitOfWorks.DbContext.Entry(item);
}
#endregion
//
#region Private ...
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEntityRegisterar.cs
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Base Entity Registerar ...
/// </summary>
public abstract class XBaseEntityRegisterar : IXEntityRegisterar
{
/// <summary>
/// Private Entity Types Collection ...
/// </summary>
private readonly List<Type> entityTypes = [];
/// <summary>
/// Name ...
/// </summary>
public string Name { get; }
protected XBaseEntityRegisterar(string name)
{
Name = name;
}
/// <summary>
/// Add Specified Entity to Collection ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public void AddEntity<TEntity, TKey>()
where TEntity : XBaseEntity<TKey>
{
entityTypes.Add(typeof(TEntity));
}
/// <summary>
/// Retrieve Registered Entity Types ...
/// </summary>
/// <returns></returns>
public IEnumerable<Type> GetEntityTypes()
{
return entityTypes;
}
/// <summary>
/// Configure Dynamic Entities ...
/// </summary>
/// <param name="modelBuilder"></param>
public virtual void ConfigureEntities(ModelBuilder modelBuilder)
{ }
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEntityTypeConfiguration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Configure an Entity Specifications ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseEntityTypeConfiguration<TEntity, TKey> : IEntityTypeConfiguration<TEntity>
where TEntity : XBaseEntity<TKey>
{
public abstract void Configure(EntityTypeBuilder<TEntity> builder);
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseInMemoryRepository.cs
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Providers
{
/// <summary>
/// a Base Repository Pattern Implementation Specially for InMemory Stores using
/// EF Core Capabilities ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseInMemoryRepository<TEntity, TKey> : IXBaseRepository<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
//
#region Props ...
private readonly XDataServiceConfiguration configuration;
private readonly IXKeyGenerator<TEntity, TKey> keyGenerator;
private readonly IXBaseRepositoryEvents<TEntity> baseRepositoryEvents;
private static readonly ConcurrentDictionary<TKey, TEntity> store = new ConcurrentDictionary<TKey, TEntity>();
#endregion
//
#region Constructor ...
public XBaseInMemoryRepository(
XDataServiceConfiguration configuration,
IXKeyGenerator<TEntity, TKey> keyGenerator = null,
IXBaseRepositoryEvents<TEntity> baseRepositoryEvents = null
)
{
this.keyGenerator = keyGenerator;
this.configuration = configuration;
this.baseRepositoryEvents = baseRepositoryEvents;
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// add a new Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> AddAsync(
TEntity item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
var isSucceed = false;
//
// Add Item to Dictionary ...
try
{
//
store[item.Id] = item;
isSucceed = true;
}
catch
{
isSucceed = false;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<TEntity>(item));
}
//
// Return Item ...
return item;
}
/// <summary>
/// add or update an Entity (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> AddOrUpdateAsync(
TEntity item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: item.Id,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
//
var isSucceed = false;
if (isExists)
{
//
try
{
//
item = await UpdateAsync(
item: item,
id: item.Id,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
isSucceed = true;
}
catch
{
isSucceed = false;
}
}
else
{
//
try
{
//
item = await AddAsync(
item: item,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
isSucceed = true;
}
catch
{
isSucceed = false;
}
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
if (isExists)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<TEntity>(item));
}
else
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<TEntity>(item));
}
}
//
return item;
}
/// <summary>
/// add a range of new Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddRangeAsync(
IEnumerable<TEntity> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return;
}
//
foreach (var item in items)
{
//
await AddAsync(
item: item,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
//
// Notify Event ...
if (
isValid &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddManyEvent(new XBaseEventModel<IEnumerable<TEntity>>(null));
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update an Entity values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> UpdateAsync(
TKey id,
TEntity item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: id,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
if (!isExists)
{
return null;
}
//
var isSucceed = false;
var exists = store[id];
//
try
{
//
exists = exists.UpdateData(
exists,
propertyBlackList: new List<string> { nameof(exists.Id) }
);
store[id] = exists;
//
isSucceed = true;
}
catch
{
isSucceed = false;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<TEntity>(item));
}
//
return exists;
}
/// <summary>
/// Update a range of Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> UpdateRangeAsync(
IEnumerable<TEntity> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = false;
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return result;
}
//
foreach (var item in items)
{
//
var updated = await UpdateAsync(
item: item,
id: item.Id,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
if (!updated.IsNullOrDefault() && !result)
{
result = true;
}
}
//
return result;
}
#endregion
//
#region Remove ...
/// <summary>
/// remove an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: id,
cancellationToken: cancellationToken
);
if (!isExists)
{
return null;
}
//
TEntity result = null;
if (softDelete && configuration.EnableSoftDelete)
{
//
store[id].Deleted = true;
result = store[id];
}
else
{
//
result = store[id];
store.TryRemove(id, out _);
}
//
return result;
}
/// <summary>
/// remove an Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> RemoveAsync(
TEntity item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = await RemoveAsync(
id: item.Id,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// remove a range of exists Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveRangeAsync(
IEnumerable<TEntity> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return;
}
//
foreach (var item in items)
{
//
await RemoveAsync(
item: item,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
}
#endregion
//
#region Count ...
/// <summary>
/// count all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.CountAsync(cancellationToken);
//
return result;
}
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
int pagesCount = count / pageSize;
//
if (count % pageSize > 0)
{
pagesCount++;
}
//
return pagesCount;
}
#endregion
//
#region Exists ...
/// <summary>
/// Check an Entity exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.AnyAsync(
cancellationToken: cancellationToken,
predicate: x => GetKey(x).ToString() == id.ToString());
//
return result;
}
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve whole items as queryable ...
/// </summary>
/// <param name="asNoTracking">a flag for Tracking behaviour</param>
/// <param name="predicate">an Expression for Filter Items ...</param>
/// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
/// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
/// <returns></returns>
public IQueryable<TEntity> AsQueryable(
bool asNoTracking = true,
Expression<Func<TEntity, bool>> predicate = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null
)
{
//
var result = store.Values.AsQueryable();
//
// Predicate ...
if (!predicate.IsNull())
{
result = result.Where(predicate);
}
//
// Apply Orders ...
if (!orderBuilder.IsNull())
{
result = orderBuilder(result);
}
//
// Apply Includes ...
if (!includeBuilder.IsNull())
{
result = includeBuilder(result);
}
//
if (asNoTracking)
{
result = result.AsNoTracking();
}
//
return result;
}
/// <summary>
/// retrieve an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(x => GetKey(x).ToString() == id.ToString())
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<TEntity>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <returns></returns>
public IAsyncEnumerable<TEntity> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null
)
{
//
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.AsAsyncEnumerable();
//
return result;
}
/// <summary>
/// find an Entity by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> FindOneAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(predicate)
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// find a collection of Entities by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<TEntity>> FindManyAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<TEntity, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(predicate)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve Entities based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<TEntity>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<TEntity, bool>> predicate = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Normalize Query ...
query = query.NormalizeQuery(configuration);
//
var items = await GetAllAsync();
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Prepare Result ...
var result = new XQueryResult<TEntity>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
//
#region Unit Of Work ...
/// <summary>
/// Save all unsaved Transactions on DbContext ...
/// used fo Unit Of Works Design Pattern ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default
)
{
//
return await Task.Run(
() => 0,
cancellationToken
);
}
#endregion
//
#region Key ...
/// <summary>
/// Retrieve Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public TKey GetKey(TEntity item)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
//
var keyString = string.Empty;
if (keyProp.IsNull())
{
keyString = string.Empty;
}
else
{
keyString = keyProp.GetValue(item).ToString();
}
//
if (keyString.IsNullOrEmpty())
{
return default(TKey);
}
//
// Prevent Deserializing issues throug JsonReader ...
if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
{
return item.Id;
}
//
return keyString.FromJSON<TKey>();
}
/// <summary>
/// Set Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="id"></param>
public void SetKey(
ref TEntity item,
TKey id
)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
if (keyProp.IsNull())
{
return;
}
//
Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
keyProp.SetValue(item, safeValue, null);
}
/// <summary>
/// Handle Checking Key ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TEntity> HandleKeyAsync(
TEntity item,
CancellationToken cancellationToken = default
)
{
//
var keyType = typeof(TKey);
//
// Handle Guid Key Type ...
// Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
if (
(
keyType == typeof(Guid) ||
keyType == typeof(string)
) &&
keyGenerator.IsEmpty(item.Id)
)
{
//
var newKey = await keyGenerator.GenerateKey(this);
//
SetKey(ref item, newKey);
}
//
return item;
}
#endregion
//
#region Detach ...
/// <summary>
/// Detach an Entity ...
/// </summary>
/// <param name="item"></param>
public void Detach(TEntity item) { }
/// <summary>
/// Detach an Enumerable of Entities ...
/// </summary>
/// <param name="items"></param>
public void Detach(IEnumerable<TEntity> items) { }
/// <summary>
/// Detach a Query Result of Entity ...
/// </summary>
/// <param name="query"></param>
public void Detach(XQueryResult<TEntity> query) { }
#endregion
#endregion
//
#region Others ...
public void Dispose()
{ }
#endregion
//
#region Private ...
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseMongoRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Providers
{
/// <summary>
/// a Base Repository Pattern Implementation Specially for Mongo DBs using
/// EF Core Capabilities ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseMongoRepository<T, TKey> : IXBaseRepository<T, TKey>
where T : XBaseEntity<TKey>
{
//
#region Properties ...
private readonly string collectionName;
public List<WriteModel<T>> bulkCollection;
public readonly IMongoCollection<T> collection;
private readonly IXKeyGenerator<T, TKey> keyGenerator;
public readonly XDataBaseConfiguration dbConfiguration;
public readonly XDataServiceConfiguration configuration;
private readonly IXBaseRepositoryEvents<T> baseRepositoryEvents;
#endregion
//
#region Constructor ...
protected XBaseMongoRepository(
XDataBaseConfiguration dbConfiguration,
XDataServiceConfiguration configuration,
string collectionName = null,
IXKeyGenerator<T, TKey> keyGenerator = null,
IXBaseRepositoryEvents<T> baseRepositoryEvents = null
)
{
//
this.keyGenerator = keyGenerator;
this.configuration = configuration;
this.collectionName = collectionName
.IsNullOrEmpty() ?
typeof(T).Name :
collectionName;
this.dbConfiguration = dbConfiguration;
this.baseRepositoryEvents = baseRepositoryEvents;
//
var client = new MongoClient(dbConfiguration.GetMongoDbURI());
var database = client.GetDatabase(dbConfiguration.GetMongoDbDatabase());
//
bulkCollection = new List<WriteModel<T>>();
collection = database.GetCollection<T>(
this.collectionName
);
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// add a new Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
// Add Action model to Bulk Collection ...
bulkCollection.Add(new InsertOneModel<T>(item));
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// add or update an Entity (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddOrUpdateAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: GetKey(item),
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
if (!isExists)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
// Add Action model to Bulk Collection ...
bulkCollection
.Add(new InsertOneModel<T>(item));
}
else
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);
//
// Add Action model to Bulk Collection ...
bulkCollection
.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
if (isExists)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<T>(item));
}
else
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<T>(item));
}
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// add a range of new Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return;
}
//
foreach (var item in items)
{
//
await AddAsync(
item: item,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
//
// Notify Event ...
if (
isValid &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update an Entity values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> UpdateAsync(
TKey id,
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, id);
//
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = false });
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// Update a range of Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> UpdateRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = false;
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return result;
}
//
foreach (var item in items)
{
//
var updated = await UpdateAsync(
item: item,
id: item.Id,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
if (!updated.IsNullOrDefault() && !result)
{
result = true;
}
}
//
return result;
}
#endregion
//
#region Remove ...
/// <summary>
/// remove an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Retrieve Item ...
var item = await GetAsync(
id: id,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
if (item.IsNull())
{
return null;
}
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, id);
//
// Check SoftDelete ...
if (softDelete && configuration.EnableSoftDelete)
{
//
// Set Soft Delete ...
item.Deleted = true;
//
// Update ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
else
{
//
// Delete ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new DeleteOneModel<T>(filter));
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// remove an Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
T item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = await RemoveAsync(
id: item.Id,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// remove a range of exists Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveRangeAsync(
IEnumerable<T> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// loop through items ...
foreach (var item in items)
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);
//
// Check Soft Delete ...
if (softDelete && configuration.EnableSoftDelete)
{
//
// Set Soft Delete ...
item.Deleted = true;
//
// Update ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
else
{
//
// Delete ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new DeleteOneModel<T>(filter));
}
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Count ...
/// <summary>
/// count all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.CountAsync(cancellationToken);
//
return result;
}
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
int pagesCount = count / pageSize;
//
if (count % pageSize > 0)
{
pagesCount++;
}
//
return pagesCount;
}
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve whole items as queryable ...
/// </summary>
/// <param name="asNoTracking">a flag for Tracking behaviour</param>
/// <param name="predicate">an Expression for Filter Items ...</param>
/// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
/// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
/// <returns></returns>
public IQueryable<T> AsQueryable(
bool asNoTracking = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
var result = collection
.AsQueryable();
//
// Apply Predicate ...
if (!predicate.IsNull())
{
result = result
.Where(predicate);
}
//
// Apply Includes ...
if (!includeBuilder.IsNull())
{
//
// Since Mongo Queryable doesnt Support Includes ...
// we ignore this ...
result = (IMongoQueryable<T>)includeBuilder(result);
}
//
// Apply Ordering ...
if (!orderBuilder.IsNull())
{
result = (IMongoQueryable<T>)orderBuilder(result);
}
//
return result;
}
/// <summary>
/// retrieve an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(x => GetKey(x).ToString() == id.ToString())
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <returns></returns>
public IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.AsAsyncEnumerable();
//
return result;
}
/// <summary>
/// find an Entity by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> FindOneAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(predicate)
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// find a collection of Entities by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> FindManyAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.Where(predicate)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve Entities based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<T>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Normalize Query ...
query = query.NormalizeQuery(configuration);
//
var items = await GetAllAsync();
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Prepare Result ...
var result = new XQueryResult<T>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
//
#region Exists ...
/// <summary>
/// Check an Entity exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.AnyAsync(
cancellationToken: cancellationToken,
predicate: x => GetKey(x).ToString() == id.ToString());
//
return result;
}
#endregion
//
#region Unit Of Work ...
/// <summary>
/// Save all unsaved Transactions on DbContext ...
/// used fo Unit Of Works Design Pattern ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Write all Bulk Models which stored inside bulkCollection ...
var result = await collection
.BulkWriteAsync(
options: null,
requests: bulkCollection,
cancellationToken: cancellationToken
);
//
// Clear Bulk Collection ...
bulkCollection.Clear();
//
// Return number of Modified Documents ...
var resultCount = (int)result.ModifiedCount +
(int)result.InsertedCount +
(int)result.DeletedCount;
//
return resultCount;
}
catch (Exception ex)
{
//
// Log Thrown Exception ...
Console.WriteLine($"XMongo Repository Exception: {ex.Message} ...");
//
// Return less than zero value ...
return -1;
}
}
#endregion
//
#region Key ...
/// <summary>
/// Retrieve Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public TKey GetKey(T item)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
//
var keyString = string.Empty;
if (keyProp.IsNull())
{
keyString = string.Empty;
}
else
{
keyString = keyProp.GetValue(item).ToString();
}
//
if (keyString.IsNullOrEmpty())
{
return default(TKey);
}
//
// Prevent Deserializing issues throug JsonReader ...
if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
{
return item.Id;
}
//
return keyString.FromJSON<TKey>();
}
/// <summary>
/// Set Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="id"></param>
public void SetKey(
ref T item,
TKey id
)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
if (keyProp.IsNull())
{
return;
}
//
Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
keyProp.SetValue(item, safeValue, null);
}
/// <summary>
/// Handle Checking Key ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> HandleKeyAsync(
T item,
CancellationToken cancellationToken = default
)
{
//
var keyType = typeof(TKey);
//
// Handle Guid Key Type ...
// Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
if (
(
keyType == typeof(Guid) ||
keyType == typeof(string)
) &&
keyGenerator.IsEmpty(item.Id)
)
{
//
var newKey = await keyGenerator.GenerateKey(this);
//
SetKey(ref item, newKey);
}
//
return item;
}
#endregion
//
#region Detach ...
/// <summary>
/// Detach an Entity ...
/// </summary>
/// <param name="item"></param>
public void Detach(T item) { }
/// <summary>
/// Detach an Enumerable of Entities ...
/// </summary>
/// <param name="items"></param>
public void Detach(IEnumerable<T> items) { }
/// <summary>
/// Detach a Query Result of Entity ...
/// </summary>
/// <param name="query"></param>
public void Detach(XQueryResult<T> query) { }
#endregion
#endregion
//
#region Others ...
public void Dispose() { }
public string GetPropValues(T item)
{
//
var props = item.GetType().GetProperties();
var vals = props.Select(p => p.GetValue(p.Name));
//
return vals.ToJSON();
}
#endregion
//
#region Private ...
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseRepositoryEvents.cs
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using xDataService.Interfaces;
using xDataService.Models;
namespace xDataService.Providers {
/// <summary>
/// Some Events can be Raised on Some Actions Happens on Repositories ...
/// this is the Base Events Class ...
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class XBaseRepositoryEvents<T> : IXBaseRepositoryEvents<T> {
//
private readonly ISubject<XBaseEventModel<T>> onAddSubject;
private readonly ISubject<XBaseEventModel<T>> onUpdateSubject;
private readonly ISubject<XBaseEventModel<T>> onRemoveSubject;
//
private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onAddManySubject;
private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onUpdateManySubject;
private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onRemoveManySubject;
//
protected XBaseRepositoryEvents () {
//
onAddSubject = new ReplaySubject<XBaseEventModel<T>> (1);
onUpdateSubject = new ReplaySubject<XBaseEventModel<T>> (1);
onRemoveSubject = new ReplaySubject<XBaseEventModel<T>> (1);
//
onAddManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
onUpdateManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
onRemoveManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
}
//
public void AddEvent (XBaseEventModel<T> model) => onAddSubject.OnNext (model);
public void UpdateEvent (XBaseEventModel<T> model) => onUpdateSubject.OnNext (model);
public void RemoveEvent (XBaseEventModel<T> model) => onRemoveSubject.OnNext (model);
//
public void AddManyEvent (XBaseEventModel<IEnumerable<T>> model) => onAddManySubject.OnNext (model);
public void UpdateManyEvent (XBaseEventModel<IEnumerable<T>> model) => onUpdateManySubject.OnNext (model);
public void RemoveManyEvent (XBaseEventModel<IEnumerable<T>> model) => onRemoveManySubject.OnNext (model);
//
public IObservable<XBaseEventModel<T>> OnAddObservable => onAddSubject.AsObservable ();
public IObservable<XBaseEventModel<T>> OnUpdateObservable => onUpdateSubject.AsObservable ();
public IObservable<XBaseEventModel<T>> OnRemoveObservable => onRemoveSubject.AsObservable ();
//
public IObservable<XBaseEventModel<IEnumerable<T>>> OnAddManyObservable => onAddManySubject.AsObservable ();
public IObservable<XBaseEventModel<IEnumerable<T>>> OnUpdateManyObservable => onUpdateManySubject.AsObservable ();
public IObservable<XBaseEventModel<IEnumerable<T>>> OnRemoveManyObservable => onRemoveManySubject.AsObservable ();
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseRepositoryService.cs
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
{
/// <summary>
/// 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:
/// <see cref="XBaseEFRepository"/>>
/// <see cref="XBaseMongoRepository"/>>
/// <see cref="XBaseInMemoryRepository"/>>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseRepositoryService<TEntity, TDto, TKey> : IXBaseRepositoryService<TEntity, TDto, TKey>
where TEntity : XBaseEntity<TKey>
where TDto : XBaseEntityDto<TKey>
{
//
#region Properties ...
/// <summary>
/// Mapper Instance ...
/// </summary>
public IMapper Mapper { get; }
/// <summary>
/// Repository Implementation for Data Manipulations ...
/// </summary>
public IXBaseRepository<TEntity, TKey> Repository { get; }
/// <summary>
/// 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 ...
/// </summary>
public MapperConfiguration MapperConfiguration { get; }
#endregion
//
#region Constructor ...
public XBaseRepositoryService(
IXBaseRepository<TEntity, TKey> repository,
IEnumerable<Profile> mapperProfiles = null
)
{
//
Repository = repository;
//
// Preparing Mapping Configurations ...
MapperConfiguration = new MapperConfiguration(cfg =>
{
//
// Add Default Profiles ...
//
// Entity To Dto ...
cfg.CreateMap<TEntity, TDto>()
.ForMember(dest => dest.Deleted, opt => opt.Ignore());
cfg.CreateMap<XQueryResult<TEntity>, XQueryResult<TDto>>();
//
// Dto to Entity ...
cfg.CreateMap<TDto, TEntity>()
.ForMember(dest => dest.Deleted, opt => opt.Ignore());
cfg.CreateMap<XQueryResult<TDto>, XQueryResult<TEntity>>();
//
// 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 ...
/// <summary>
/// add a new Dto ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> 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<TEntity>(item);
//
entity = await Repository.AddAsync(
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// add or update a Dto (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> 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<TEntity>(item);
//
entity = await Repository.AddOrUpdateAsync(
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// add a range of new Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddRangeAsync(
IEnumerable<TDto> 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<IEnumerable<TEntity>>(items);
//
await Repository.AddRangeAsync(
items: entities,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{ }
}
#endregion
//
#region Update ...
/// <summary>
/// Update an Dto values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> UpdateAsync(
TKey id,
TDto item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = Mapper.Map<TEntity>(item);
//
entity = await Repository.UpdateAsync(
id: item.Id,
item: entity,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// Update a range of Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> UpdateRangeAsync(
IEnumerable<TDto> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var result =
!items.IsNull() &&
items.HasChild();
if (!result)
{
return result;
}
//
try
{
//
var entitis = Mapper.Map<IEnumerable<TEntity>>(items);
//
result = await Repository.UpdateRangeAsync(
items: entitis,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{
result = false;
}
//
return result;
}
#endregion
//
#region Remove ...
/// <summary>
/// remove an Dto by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> 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<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// remove an Dto ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> RemoveAsync(
TDto item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
TDto result = null;
//
try
{
//
var entity = Mapper.Map<TEntity>(item);
//
entity = await Repository.RemoveAsync(
item: entity,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
result = Mapper.Map<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// remove a range of exists Dtos ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveRangeAsync(
IEnumerable<TDto> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!items.IsNull() &&
items.HasChild();
if (!isValid)
{
return;
}
//
var entities = Mapper.Map<IEnumerable<TEntity>>(items);
//
try
{
//
await Repository.RemoveRangeAsync(
items: entities,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
catch
{ }
}
#endregion
//
#region Count ...
/// <summary>
/// count all exists Dtos ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
var result = await Repository.CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
return result;
}
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> 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 ...
/// <summary>
/// Check a Dto exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> 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 ...
/// <summary>
/// retrieve an Dto by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> 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<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// retrieve all exists Dtos ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<TDto>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
IEnumerable<TDto> result = Enumerable.Empty<TDto>();
//
try
{
//
var entities = await Repository.GetAllAsync(
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map<IEnumerable<TDto>>(entities);
}
catch
{ }
//
return result;
}
/// <summary>
/// retrieve all exists Dtos
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> 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<TDto>(entity);
yield return dto;
}
}
/// <summary>
/// find an Dto by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<TDto> FindOneAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> 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<TDto>(entity);
}
catch
{ }
//
return result;
}
/// <summary>
/// find a collection of Dtos by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<TDto>> FindManyAsync(
Expression<Func<TEntity, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
IEnumerable<TDto> result = Enumerable.Empty<TDto>();
//
try
{
//
var entities = await Repository.FindManyAsync(
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map<IEnumerable<TDto>>(entities);
}
catch
{ }
//
return result;
}
/// <summary>
/// retrieve Dtos based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<TDto>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<TEntity, bool>> predicate = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
XQueryResult<TDto> result = null;
//
try
{
//
var entityResult = await Repository.QueryAsync(
query: query,
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
//
result = Mapper.Map<XQueryResult<TDto>>(entityResult);
}
catch
{ }
//
return result;
}
#endregion
public virtual void Dispose()
{ }
#endregion
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XEntityRegisterarHandlerService.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Interfaces;
namespace xDataService.Providers
{
public class XEntityRegisterarHandlerService
{
/// <summary>
/// a Collection for Extract Registerars Services ...
/// </summary>
private readonly List<IXEntityRegisterar> registerars = [];
/// <summary>
/// a Collection for Holding all Entity Types ...
/// </summary>
public IReadOnlyList<Type> AllEntityTypes { get; private set; }
/// <summary>
/// Retrieve Specified Registerars Entity Types ...
/// </summary>
/// <param name="names"></param>
/// <returns></returns>
public IReadOnlyList<Type> GetEntityTypes(string[] names = null)
{
//
var items = new List<Type>();
//
if (!names.IsNull() && names.HasChild())
{
//
items = [.. registerars
.Where(r => names.Contains(r.Name))
.SelectMany(r => r.GetEntityTypes())];
}
//
return items.AsReadOnly();
}
/// <summary>
/// Load all Dynamically Registered Entities ...
/// </summary>
public void HandleRegisteredEntities()
{
//
var entityTypes = new List<Type>();
// path = Path.Combine (Directory.GetCurrentDirectory ());
var path = Path.Combine (AppContext.BaseDirectory);
var files = Directory.GetFiles(path, "*.dll");
foreach (var dll in files)
{
//
// Retrieve DLL Assembly ...
var assembly = Assembly.LoadFrom(dll);
//
// Extract Registerar Types ...
var registerarTypes = assembly
.GetExportedTypes()
.Where(t =>
!t.IsAbstract &&
typeof(IXEntityRegisterar).IsAssignableFrom(t));
foreach (var registerarType in registerarTypes)
{
//
// Create Instance of Registerar Type ...
var registerar = (IXEntityRegisterar)Activator.CreateInstance(registerarType);
if (!registerar.IsNull())
{
//
// Add Registerar Instance to Collection ...
registerars.Add(registerar);
//
// Add Registerar Provided Entities to Collection ...
entityTypes.AddRange(registerar.GetEntityTypes());
}
}
//
// Converts to Readonly List ...
AllEntityTypes = entityTypes.AsReadOnly();
}
}
/// <summary>
/// Configure all Dynamically Registered Entities ...
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="names"></param>
public void HandleApplyRegisteredEntitiesConfigurations(
ModelBuilder modelBuilder,
string[] names = null
)
{
//
var selectedRegisterars =
!names.IsNull() &&
names.HasChild()
? registerars
.Where(r => names.Contains(r.Name))
: registerars;
//
// Loop Through Extracted Registerars ...
foreach(var registerar in selectedRegisterars)
{
//
// Configure Specified Registerars Entities ...
registerar.ConfigureEntities(modelBuilder);
}
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XGuidKeyGenerator.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Default Guid Key Generator ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class XGuidKeyGenerator<TEntity> : XKeyGenerator<TEntity, Guid>, IXKeyGenerator<TEntity, Guid>
where TEntity : XBaseEntity<Guid>
{
private readonly IXSequentialGuid sequentialGuid;
public XGuidKeyGenerator(
IXSequentialGuid sequentialGuid = null
)
{
this.sequentialGuid = sequentialGuid;
}
public override async Task<Guid> GenerateKey(
IXBaseRepository<TEntity, Guid> repository,
CancellationToken cancellationToken = default
)
{
//
return await Task.Run(() =>
{
//
// Check if provided SequentialGuid ...
if (sequentialGuid.IsNull())
{
return Guid.NewGuid();
}
else
{
return sequentialGuid.Next();
}
}, cancellationToken: cancellationToken);
}
public override bool IsEmpty(Guid id)
{
//
var result = id.IsNull() || id.IsDefaultGuid();
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XIntKeyGenerator.cs
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Default Int Key Generator ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class XIntKeyGenerator<TEntity> : XKeyGenerator<TEntity, int>, IXKeyGenerator<TEntity, int>
where TEntity : XBaseEntity<int>
{
public override async Task<int> GenerateKey(
IXBaseRepository<TEntity, int> repository,
CancellationToken cancellationToken = default
)
{
//
var items = (await repository.GetAllAsync())
.OrderByDescending(nameof(XBaseEntity<int>.Id));
var last = items
.FirstOrDefault();
//
var result = last.IsNull() ? 1 : last.Id + 1;
//
return result;
}
public override bool IsEmpty(int id)
{
//
var result = id <= 0;
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XKeyGenerator.cs
using System.Threading;
using System.Threading.Tasks;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
public abstract class XKeyGenerator<TEntity, TKey> : IXKeyGenerator<TEntity, TKey>
where TEntity : XBaseEntity<TKey>
{
public abstract Task<TKey> GenerateKey(
IXBaseRepository<TEntity, TKey> repository,
CancellationToken cancellationToken = default
);
public abstract bool IsEmpty(TKey id);
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XLongKeyGenerator.cs
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Default Long Key Generator ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class XLongKeyGenerator<TEntity> : XKeyGenerator<TEntity, long>, IXKeyGenerator<TEntity, long>
where TEntity : XBaseEntity<long>
{
public override async Task<long> GenerateKey(
IXBaseRepository<TEntity, long> repository,
CancellationToken cancellationToken = default
)
{
//
var items = (await repository.GetAllAsync())
.OrderByDescending(nameof(XBaseEntity<long>.Id));
var last = items
.FirstOrDefault();
//
var result = last.IsNull() ? 1 : last.Id + 1;
//
return result;
}
public override bool IsEmpty(long id)
{
//
var result = id <= 0;
//
return result;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XSequentialGuid.cs
using System;
using xDataService.Interfaces;
namespace xDataService.Helpers
{
/// <summary>
/// this service provide Sequential GUID mechanism for Entity Ids ...
/// </summary>
public class XSequentialGuid : IXSequentialGuid
{
private static int[] sqlOrderMap = null;
private static int[] SQLORDERMAP
{
get
{
if (sqlOrderMap == null)
{
sqlOrderMap = new int[16] {
3,
2,
1,
0,
5,
4,
7,
6,
9,
8,
15,
14,
13,
12,
11,
10
};
// 3 - the least significant byte in Guid ByteArray [for SQL Server ORDER BY clause]
// 10 - the most significant byte in Guid ByteArray [for SQL Server ORDERY BY clause]
}
return sqlOrderMap;
}
}
private Guid currentGuid;
public XSequentialGuid()
{
currentGuid = Guid.NewGuid();
}
public Guid GetCurrentGuid()
{
return currentGuid;
}
public Guid Next()
{
byte[] bytes = currentGuid.ToByteArray();
for (int mapIndex = 0; mapIndex < 16; mapIndex++)
{
int bytesIndex = SQLORDERMAP[mapIndex];
bytes[bytesIndex]++;
if (bytes[bytesIndex] != 0)
{
break; // No need to increment more significant bytes
}
}
currentGuid = new Guid(bytes);
return currentGuid;
}
}
}
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XStringKeyGenerator.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;
namespace xDataService.Providers
{
/// <summary>
/// Default Guid Key Generator ...
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class XStringKeyGenerator<TEntity> : XKeyGenerator<TEntity, string>, IXKeyGenerator<TEntity, string>
where TEntity : XBaseEntity<string>
{
private readonly IXSequentialGuid sequentialGuid;
public XStringKeyGenerator(IXSequentialGuid sequentialGuid = null)
{
this.sequentialGuid = sequentialGuid;
}
public override async Task<string> GenerateKey(
IXBaseRepository<TEntity, string> repository,
CancellationToken cancellationToken = default
)
{
//
await Task.CompletedTask;
//
if (sequentialGuid.IsNull())
{
return Guid.NewGuid().ToString();
}
else
{
return sequentialGuid.Next().ToString();
}
}
public override bool IsEmpty(string id)
{
return id.IsNullOrEmpty();
}
}
}