13289 lines
420 KiB
Plaintext
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();
|
|
}
|
|
}
|
|
}
|