diff --git a/Controllers/XBaseEntityController.cs b/Controllers/XBaseEntityController.cs
index ae8ac76..168587a 100644
--- a/Controllers/XBaseEntityController.cs
+++ b/Controllers/XBaseEntityController.cs
@@ -7,474 +7,707 @@ using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
-using xModels.Interfaces;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
using xDataService.Interfaces;
+using System.Linq;
+using Microsoft.EntityFrameworkCore.Query;
+using System.Threading;
+using SQLitePCL;
-namespace xDataService.Controllers {
+namespace xDataService.Controllers
+{
+ ///
+ /// an Abstract Controller for Providing Entity Repository Actions Implementatin ...
+ ///
+ ///
+ ///
public abstract class XBaseEntityController : XBaseController, IXEntityControllerActions
- where TEntity : XBaseEntity {
- public readonly IXBaseRepository repository;
+ where TEntity : XBaseEntity
+ {
+ //
+ #region Properties ...
+ public IXBaseRepository Repository { get; }
- protected XBaseEntityController (
- ILogger logger,
- XAppConfiguration appConfiguration,
- XValidationProvider validationProvider,
- IXBaseRepository repository
- ) : base (
- logger,
- appConfiguration,
- validationProvider
- ) {
- //
- this.repository = repository;
- }
+ public Func, IOrderedQueryable> DefaultOrderBuilder { get; }
+ public Func, IIncludableQueryable> DefaultIncludeBuilder { get; }
+ #endregion
+
+ //
+ #region Constructor ...
+ protected XBaseEntityController(
+ ILogger> logger,
+ XAppConfiguration appConfiguration,
+ XValidationProvider validationProvider,
+ IXBaseRepository repository,
+ Func, IOrderedQueryable> defaultOrderBuilder = null,
+ Func, IIncludableQueryable> defaultIncludeBuilder = null
+ ) : base(
+ logger,
+ appConfiguration,
+ validationProvider
+ )
+ {
//
- #region Interface Implementations ...
- //
- #region Retrieve ...
- [HttpGet ("{id}")]
- public virtual async Task> Get (
- [FromRoute] TKey id, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotNull (id);
-
- //
- // Get Result ...
- var result = await repository
- .GetAsync (
- id,
- ignoreSoftDeleteds : ignoreSoftDeleteds,
- containsDetail : containsDetail
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpGet]
- public virtual async Task>> GetAll (
- [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
- ) {
- //
- try {
- //
- // Get Result ...
- var result = await repository
- .GetAllAsync (
- ignoreSoftDeleteds: ignoreSoftDeleteds,
- containsDetail: containsDetail
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpGet ("FindOne/{query}")]
- public virtual async Task> FindOne (
- [FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotEmpty (query);
-
- //
- // Get Result ...
- var result = await repository
- .FindOneAsync (t =>
- t.PropValuesContains (query),
- ignoreSoftDeleteds : ignoreSoftDeleteds,
- containsDetail : containsDetail
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpGet ("FindMany/{query}")]
- public virtual async Task>> FindMany (
- [FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotEmpty (query);
-
- //
- // Get Result ...
- var result = await repository
- .FindManyAsync (t =>
- t.PropValuesContains (query),
- ignoreSoftDeleteds : ignoreSoftDeleteds,
- containsDetail : containsDetail
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpGet ("Query")]
- public virtual async Task>> Query (
- [FromQuery] XQuery query, [FromQuery] bool ignoreSoftDeleteds = true
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotNull (query);
-
- //
- // Get Result ...
- var result = await repository
- .QueryAsync (
- query,
- ignoreSoftDeleteds : ignoreSoftDeleteds
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- //
- // TODO: Fix this ...
- // [HttpGet ("RequestPage")]
- // public virtual async Task>> RequestPage (
- // [FromQuery] XPageRequest request, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
- // ) {
- // //
- // try {
- // //
- // // Validate Args ...
- // ValidationProvider.NotNull (request);
-
- // //
- // // Get Result ...
- // var result = await repository
- // .RequestPageAsync (
- // request,
- // ignoreSoftDeleteds : ignoreSoftDeleteds,
- // containsDetail : containsDetail
- // );
-
- // //
- // return Ok (result
- // .ToDynamicObject ());
- // } catch (Exception ex) {
- // //
- // var result = GetExceptionActionResult (ex);
- // return result;
- // }
- // }
- #endregion
-
- //
- #region Add ...
- [HttpPost]
- public virtual async Task> Add (
- [FromBody] TEntity item
- ) {
- //
- try {
- //
- // Validate Args ...
- if (!ModelState.IsValid) {
- XException.InvalidArgs.Throw ();
- }
- ValidationProvider.NotNull (item);
-
- //
- // Get Result ...
- var result = await repository
- .AddAsync (
- item,
- saveChanges : true
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpPost ("AddOrUpdate")]
- public virtual async Task> AddOrUpdate (
- [FromBody] TEntity item
- ) {
- //
- try {
- //
- // Validate Args ...
- if (!ModelState.IsValid) {
- XException.InvalidArgs.Throw ();
- }
- ValidationProvider.NotNull (item);
-
- //
- // Get Result ...
- var result = await repository
- .AddOrUpdateAsync (
- item,
- saveChanges : true
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpPost ("AddMany")]
- public virtual async Task AddMany (
- [FromBody] XBaseRangeRequest request
- ) {
- //
- 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
- );
-
- //
- return Ok ();
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
- #endregion
-
- //
- #region Update ...
- [HttpPut ("{id}")]
- public virtual async Task> Update (
- [FromRoute] TKey id, [FromBody] TEntity item
- ) {
- //
- try {
- //
- // Validate Args ...
- if (!ModelState.IsValid) {
- XException.InvalidArgs.Throw ();
- }
- await ValidationProvider
- .GroupValidationBuilder ()
- .AddNotNull (id, item)
- .ValidateGroupAsync ();
-
- //
- // Get Result ...
- var result = await repository
- .UpdateAsync (
- id,
- item,
- saveChanges : true
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpPost ("UpdateMany")]
- public virtual async Task> UpdateMany (
- [FromBody] XBaseRangeRequest request
- ) {
- //
- 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 (
- request.Items,
- saveChanges : true
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
- #endregion
-
- //
- #region Exists ...
- [HttpGet ("{id}/IsExists")]
- public virtual async Task> IsExists (
- [FromRoute] TKey id, [FromQuery] bool ignoreSoftDeleteds = true
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotNull (id);
-
- //
- // Get Result ...
- var result = await repository
- .IsExistsAsync (
- id,
- ignoreSoftDeleteds : ignoreSoftDeleteds
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
- #endregion
-
- //
- #region Remove ...
- [HttpDelete ("{id}")]
- public virtual async Task> Remove (
- [FromRoute] TKey id,
- bool softDelete = true
- ) {
- //
- try {
- //
- // Validate Args ...
- ValidationProvider.NotNull (id);
-
- //
- // Get Result ...
- var result = await repository
- .RemoveAsync (
- id,
- saveChanges : true,
- softDelete : softDelete
- );
-
- //
- return Ok (result
- .ToDynamicObject ());
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
-
- [HttpPost ("RemoveMany")]
- public virtual async Task RemoveMany (
- [FromBody] XBaseRangeRequest request,
- bool softDelete = true
- ) {
- //
- try {
- //
- // Validate Args ...
- await ValidationProvider
- .GroupValidationBuilder ()
- .AddNotNull (request)
- .AddNotZeroChilds (request.Items)
- .ValidateGroupAsync ();
-
- //
- // Get Result ...
- await repository
- .RemoveRangeAsync (
- request.Items,
- saveChanges : true,
- softDelete : softDelete
- );
-
- //
- return Ok ();
- } catch (Exception ex) {
- //
- var result = GetExceptionActionResult (ex);
- return result;
- }
- }
- #endregion
- #endregion
+ Repository = repository;
+ DefaultOrderBuilder = defaultOrderBuilder;
+ DefaultIncludeBuilder = defaultIncludeBuilder;
}
+ #endregion
+
+ //
+ #region Actions ...
+ //
+ #region Add ...
+ ///
+ /// Add Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Add or Update Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("AddOrUpdate")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Add a Collection of Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("AddMany")]
+ public virtual async Task AddMany(
+ [FromBody] XBaseRangeRequest 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 ...
+ ///
+ /// Get Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Get All Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public virtual async Task>> 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;
+ }
+ }
+
+ ///
+ /// Find Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("FindOne/{query}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Find Many Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("FindMany/{query}")]
+ public virtual async Task>> 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;
+ }
+ }
+
+ ///
+ /// Retrieve Items Based on Query Mechanism ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("Query")]
+ public virtual async Task>> 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 ...
+ ///
+ /// Update Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPut("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Update a Collection of items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("UpdateMany")]
+ public virtual async Task> UpdateMany(
+ [FromBody] XBaseRangeRequest 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 ...
+ ///
+ ///Check an Item Exists or not ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("{id}/IsExists")]
+ public virtual async Task> 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 ...
+ ///
+ /// Remove an Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpDelete("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Remove Many Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("RemoveMany")]
+ public virtual async Task RemoveMany(
+ [FromBody] XBaseRangeRequest 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
+ }
}
\ No newline at end of file
diff --git a/Controllers/XBaseEntityDtoController.cs b/Controllers/XBaseEntityDtoController.cs
new file mode 100644
index 0000000..d043740
--- /dev/null
+++ b/Controllers/XBaseEntityDtoController.cs
@@ -0,0 +1,712 @@
+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 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
+{
+ ///
+ /// an Abstract Controller for Providing Entity Dto Repository Service Actions Implementatin ...
+ ///
+ ///
+ ///
+ ///
+ public abstract class XBaseEntityDtoController : XBaseController, IXEntityDtoControllerActions
+ where TEntity : XBaseEntity
+ where TDto : XBaseEntityDto
+ {
+ //
+ #region Properties ...
+ public IXBaseRepositoryService RepositoryService { get; }
+ public Func, IOrderedQueryable> DefaultOrderBuilder { get; }
+ public Func, IIncludableQueryable> DefaultIncludeBuilder { get; }
+ #endregion
+
+ //
+ #region Constructor ...
+ protected XBaseEntityDtoController(
+ ILogger> logger,
+ XAppConfiguration appConfiguration,
+ XValidationProvider validationProvider,
+ IXBaseRepositoryService repositoryService,
+ Func, IOrderedQueryable> defaultOrderBuilder = null,
+ Func, IIncludableQueryable> defaultIncludeBuilder = null
+ ) : base(
+ logger,
+ appConfiguration,
+ validationProvider
+ )
+ {
+ //
+ RepositoryService = repositoryService;
+ DefaultOrderBuilder = defaultOrderBuilder;
+ DefaultIncludeBuilder = defaultIncludeBuilder;
+ }
+ #endregion
+
+ //
+ #region Actions ...
+ //
+ #region Add ...
+ ///
+ /// Add Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Add or Update Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("AddOrUpdate")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Add a Collection of Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("AddMany")]
+ public virtual async Task AddMany(
+ [FromBody] XBaseRangeRequest 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 ...
+ ///
+ /// Get Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Get All Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public virtual async Task>> 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;
+ }
+ }
+
+ ///
+ /// Find Specified Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("FindOne/{query}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Find Many Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("FindMany/{query}")]
+ public virtual async Task>> 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;
+ }
+ }
+
+ ///
+ /// Retrieve Items Based on Query Mechanism ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("Query")]
+ public virtual async Task>> 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 ...
+ ///
+ /// Update Item ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPut("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Update a Collection of items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("UpdateMany")]
+ public virtual async Task> UpdateMany(
+ [FromBody] XBaseRangeRequest 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 ...
+ ///
+ ///Check an Item Exists or not ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("{id}/IsExists")]
+ public virtual async Task> 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 ...
+ ///
+ /// Remove an Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpDelete("{id}")]
+ public virtual async Task> 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;
+ }
+ }
+
+ ///
+ /// Remove Many Items ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("RemoveMany")]
+ public virtual async Task RemoveMany(
+ [FromBody] XBaseRangeRequest 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
+ }
+}
\ No newline at end of file
diff --git a/Db/XUnitOfWorks.cs b/Db/XUnitOfWorks.cs
index ca57bea..1975202 100644
--- a/Db/XUnitOfWorks.cs
+++ b/Db/XUnitOfWorks.cs
@@ -1,3 +1,4 @@
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
@@ -32,9 +33,12 @@ namespace xDataService.Db {
///
/// Save Changes Async
///
+ ///
///
- public async Task SaveChangesAsync () {
- return await DbContext.SaveChangesAsync ();
+ public async Task SaveChangesAsync (
+ CancellationToken cancellationToken = default
+ ) {
+ return await DbContext.SaveChangesAsync (cancellationToken);
}
public void Dispose () {
diff --git a/EFRepositories/XBaseEFRepository.cs b/EFRepositories/XBaseEFRepository.cs
index 5326fd1..4257659 100644
--- a/EFRepositories/XBaseEFRepository.cs
+++ b/EFRepositories/XBaseEFRepository.cs
@@ -2,41 +2,42 @@ 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.ChangeTracking;
+using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
-using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.EFRepositories
{
///
- /// Base EFCore Base Entity Repository Pattern implementation ...
- /// Only Used on EFCore ...
+ /// a Base Repository Pattern Implementation Specially for EF DBs using
+ /// EF Core Capabilities ...
///
- /// is the Entity type
- /// is the Entity Key Type
- /// is the DbContext Type
+ ///
+ ///
+ ///
public abstract class XBaseEFRepository : IXBaseRepository
where T : XBaseEntity
where TDbContext : XDbContext
{
+ //
+ #region Properties ...
//
public readonly DbSet dbSet;
private readonly IXKeyGenerator keyGenerator;
public readonly IXUnitOfWorks unitOfWorks;
public readonly XDataServiceConfiguration configuration;
private readonly IXBaseRepositoryEvents baseRepositoryEvents;
-
- //
- public abstract IQueryable GetFullDbSet();
+ #endregion
//
#region Constructor ...
@@ -47,28 +48,44 @@ namespace xDataService.EFRepositories
IXBaseRepositoryEvents baseRepositoryEvents = null
)
{
- this.keyGenerator = keyGenerator;
//
this.unitOfWorks = unitOfWorks;
+ this.keyGenerator = keyGenerator;
this.configuration = configuration;
this.dbSet = unitOfWorks.GetDbSet();
this.baseRepositoryEvents = baseRepositoryEvents;
}
#endregion
+ //
+ #region Actions ...
//
#region Add ...
+ ///
+ /// add a new Entity ...
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task AddAsync(
T item,
- bool saveChanges = true
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
)
{
//
// Handle Key ...
- item = await HandleKeyAsync(item);
+ item = await HandleKeyAsync(
+ item: item,
+ cancellationToken: cancellationToken
+ );
//
- var entry = await dbSet.AddAsync(item);
+ var entry = await dbSet.AddAsync(
+ entity: item,
+ cancellationToken: cancellationToken
+ );
//
// Check action is Succeeded or not ...
@@ -77,7 +94,7 @@ namespace xDataService.EFRepositories
{
//
// Get Modified Count ...
- var qResult = await SaveChangesAsync();
+ var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
@@ -91,6 +108,7 @@ namespace xDataService.EFRepositories
!baseRepositoryEvents.IsNull()
)
{
+ //
baseRepositoryEvents
.AddEvent(new XBaseEventModel(entry.Entity));
}
@@ -102,42 +120,67 @@ namespace xDataService.EFRepositories
null;
}
+ ///
+ /// add or update an Entity (add if not exists/update if exists) ...
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task AddOrUpdateAsync(
T item,
- bool saveChanges = true
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
)
{
//
- var isExists = await IsExistsAsync(GetKey(item));
+ var isExists = await IsExistsAsync(
+ id: GetKey(item),
+ cancellationToken: cancellationToken
+ );
if (!isExists)
{
+ //
return await AddAsync(
- item,
- saveChanges
+ item: item,
+ saveChanges: saveChanges,
+ cancellationToken: cancellationToken
);
}
else
{
+ //
return await UpdateAsync(
- GetKey(item),
- item,
- saveChanges
+ item: item,
+ id: GetKey(item),
+ saveChanges: saveChanges,
+ cancellationToken: cancellationToken
);
}
}
+ ///
+ /// add a range of new Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task AddRangeAsync(
IEnumerable items,
- bool saveChanges = true
+ 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
);
//
@@ -147,7 +190,7 @@ namespace xDataService.EFRepositories
{
//
// Get Modified Count ...
- var qResult = await SaveChangesAsync();
+ var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
@@ -161,27 +204,156 @@ namespace xDataService.EFRepositories
!baseRepositoryEvents.IsNull()
)
{
+ //
baseRepositoryEvents
.AddManyEvent(new XBaseEventModel>(null));
}
}
#endregion
+ //
+ #region Update ...
+ ///
+ /// Update an Entity values ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task 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(entry.Entity));
+ }
+
+ //
+ // Return result base on action Succeed ...
+ return isSucceed ?
+ entry.Entity :
+ null;
+ }
+
+ ///
+ /// Update a range of Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task UpdateRangeAsync(
+ IEnumerable 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>(null));
+ }
+
+ //
+ // Return result base on action Succeed ...
+ return isSucceed;
+ }
+ #endregion
+
//
#region Remove ...
+ ///
+ /// remove an Entity by it's Id ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task RemoveAsync(
TKey id,
bool softDelete = true,
- bool saveChanges = true
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
)
{
//
// Retrieve Item ...
var item = await GetAsync(
id,
- ignoreSoftDeleteds: false
+ ignoreSoftDeleteds: false,
+ cancellationToken: cancellationToken
);
- if (item.IsNull())
+ if (item.IsNullOrDefault())
{
return null;
}
@@ -207,7 +379,7 @@ namespace xDataService.EFRepositories
{
//
// Get Modified Count ...
- var qResult = await SaveChangesAsync();
+ var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
@@ -221,6 +393,7 @@ namespace xDataService.EFRepositories
!baseRepositoryEvents.IsNull()
)
{
+ //
baseRepositoryEvents
.RemoveEvent(new XBaseEventModel(entry.Entity));
}
@@ -232,73 +405,46 @@ namespace xDataService.EFRepositories
null;
}
+ ///
+ /// remove an Entity ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task RemoveAsync(
T item,
bool softDelete = true,
- bool saveChanges = true
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
)
{
//
- // Check item Exists ...
- var isExists = await IsExistsAsync(
- GetKey(item),
- ignoreSoftDeleteds: false
+ var result = await RemoveAsync(
+ id: item.Id,
+ softDelete: softDelete,
+ saveChanges: saveChanges,
+ cancellationToken: cancellationToken
);
- if (!isExists)
- {
- return null;
- }
//
- // Handle Remove ...
- EntityEntry 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();
-
- //
- // set isSucceed Value based on Changes ...
- isSucceed = qResult > 0;
- }
-
- //
- // Notify Event ...
- if (
- isSucceed &&
- !baseRepositoryEvents.IsNull()
- )
- {
- baseRepositoryEvents
- .RemoveEvent(new XBaseEventModel(entry.Entity));
- }
-
- //
- // Return result base on action Succeed ...
- return isSucceed ?
- entry.Entity :
- null;
+ return result;
}
+ ///
+ /// remove a range of exists Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task RemoveRangeAsync(
IEnumerable items,
bool softDelete = true,
- bool saveChanges = true
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
)
{
//
@@ -326,7 +472,7 @@ namespace xDataService.EFRepositories
{
//
// Get Modified Count ...
- var qResult = await SaveChangesAsync();
+ var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
@@ -340,624 +486,67 @@ namespace xDataService.EFRepositories
!baseRepositoryEvents.IsNull()
)
{
+ //
baseRepositoryEvents
.RemoveManyEvent(new XBaseEventModel>(null));
}
}
#endregion
- //
- #region Retrieve ...
- public IQueryable AsQueryable()
- {
- return dbSet.AsQueryable();
- }
-
- public async Task GetAsync(
- TKey id,
- bool ignoreSoftDeleteds = true,
- bool containsDetail = false
- )
- {
- //
- var result = await FindOneAsync(i =>
- GetKey(i)
- .ToString() ==
- id
- .ToString(),
- ignoreSoftDeleteds: ignoreSoftDeleteds,
- containsDetail: containsDetail
- );
-
- //
- return result;
- }
-
- public async Task> GetAllAsync(
- bool ignoreSoftDeleteds = true,
- bool containsDetail = false
- )
- {
- return await Task.Run(() =>
- {
- //
- var result = GetDbSet(
- containsDetail: containsDetail
- );
-
- //
- // Handle Soft Deleted Items ...
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
- {
- result = result.Where(x => x.Deleted == false);
- }
-
- //
- return result.AsEnumerable();
- });
- }
-
- public async Task FindOneAsync(
- Expression> whereClause,
- bool ignoreSoftDeleteds = true,
- bool containsDetail = false
- )
- {
- //
- // Generate Where Function ...
- var whereFunc = whereClause.Compile();
-
- //
- // Handle Soft Deleted Items ...
- Func ignoreSoftDeletedsWhereFunc = null;
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
- {
- //
- Expression> ignoreSoftDeletedsWhereClause = x => x.Deleted == false;
- ignoreSoftDeletedsWhereFunc = ignoreSoftDeletedsWhereClause.Compile();
- }
-
- //
- // Get Enumerable ...
- var enumerator = GetDbSet(
- containsDetail: containsDetail
- )
- .AsAsyncEnumerable();
-
- //
- T result = null;
- await
- foreach (var entity in enumerator)
- {
- //
- var isApproved = whereFunc(entity) &&
- (ignoreSoftDeletedsWhereFunc.IsNull() ?
- true :
- ignoreSoftDeletedsWhereFunc(entity));
- if (isApproved)
- {
- //
- result = entity;
- break;
- }
- }
-
- //
- return result;
- }
-
- public async Task> FindManyAsync(
- Expression> whereClause,
- bool ignoreSoftDeleteds = true,
- bool containsDetail = false
- )
- {
- //
- // Generate Where Function ...
- var whereFunc = whereClause.Compile();
-
- //
- // Handle Soft Deleted Items ...
- Func ignoreSoftDeletedsWhereFunc = null;
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
- {
- //
- Expression> ignoreSoftDeletedsWhereClause = x => x.Deleted == false;
- ignoreSoftDeletedsWhereFunc = ignoreSoftDeletedsWhereClause.Compile();
- }
-
- //
- // Get Enumerable ...
- var enumerator = GetDbSet(
- containsDetail: containsDetail
- )
- .AsAsyncEnumerable();
-
- //
- var result = new List();
- await
- foreach (var entity in enumerator)
- {
- //
- var isApproved = whereFunc(entity) &&
- (ignoreSoftDeletedsWhereFunc.IsNull() ?
- true :
- ignoreSoftDeletedsWhereFunc(entity));
- if (isApproved)
- {
- result.Add(entity);
- }
- }
-
- //
- return result.AsEnumerable();
- }
-
- public async Task> QueryAsync(
- XQuery query,
- bool ignoreSoftDeleteds = true
- )
- {
- //
- // Validate ...
- if (query.IsNull())
- {
- XException.InvalidArgs.Throw();
- }
-
- //
- // Normalize ...
- query = query.NormalizeQuery(configuration);
-
- //
- // Handle Soft Deleted Items ...
- Func ignoreSoftDeletedsWhereFunc = null;
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
- {
- //
- Expression> ignoreSoftDeletedsWhereClause = x => x.Deleted == false;
- ignoreSoftDeletedsWhereFunc = ignoreSoftDeletedsWhereClause.Compile();
- }
-
- //
- // Get Enumerable ...
- var enumerator = GetDbSet(
- containsDetail: query.ContainsDetail
- )
- .AsAsyncEnumerable();
-
- //
- var totalEntities = new List();
- await
- foreach (var entity in enumerator)
- {
- //
- var isApproved = (ignoreSoftDeletedsWhereFunc.IsNull() ?
- true :
- ignoreSoftDeletedsWhereFunc(entity));
- if (isApproved)
- {
- totalEntities.Add(entity);
- }
- }
-
- //
- var items = totalEntities.AsEnumerable();
- 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
- {
- Page = query.Page,
- Items = items.ToList(),
- PageSize = query.PageSize,
- TotalPages = totalPagesCount,
- TotalItems = totalItemsCount,
- TotalFilteredPages = filteredPagesCount,
- TotalFilteredItems = filteredItemsCount
- };
-
- //
- return result;
- }
-
- public async Task> ConditionalQueryAsync(
- Expression> condition,
- XQuery query,
- bool ignoreSoftDeleteds = true
- )
- {
- //
- // Validate ...
- if (query.IsNull() || condition.IsNull())
- {
- XException.InvalidArgs.Throw();
- }
-
- //
- // Normalize ...
- query = query.NormalizeQuery(configuration);
-
- //
- // Handle Soft Deleted Items ...
- Func ignoreSoftDeletedsWhereFunc = null;
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
- {
- //
- Expression> ignoreSoftDeletedsWhereClause = x => x.Deleted == false;
- ignoreSoftDeletedsWhereFunc = ignoreSoftDeletedsWhereClause.Compile();
- }
-
- //
- // Compile Condition ...
- Func conditionFunc = condition.Compile();
-
- //
- // Get Enumerable ...
- var enumerator = GetDbSet(
- containsDetail: query.ContainsDetail
- )
- .AsAsyncEnumerable();
-
- //
- var totalEntities = new List();
- await
- foreach (var entity in enumerator)
- {
- //
- var isApproved = (ignoreSoftDeletedsWhereFunc.IsNull() ?
- true :
- ignoreSoftDeletedsWhereFunc(entity)) &&
- conditionFunc(entity);
- if (isApproved)
- {
- totalEntities.Add(entity);
- }
- }
-
- //
- var items = totalEntities.AsEnumerable();
- 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
- {
- Page = query.Page,
- Items = items.ToList(),
- PageSize = query.PageSize,
- TotalPages = totalPagesCount,
- TotalItems = totalItemsCount,
- TotalFilteredPages = filteredPagesCount,
- TotalFilteredItems = filteredItemsCount
- };
-
- //
- return result;
- }
-
- //
- // TODO: Fix this ...
- // public Task> RequestPageAsync (
- // XPageRequest request,
- // bool ignoreSoftDeleteds = true,
- // bool containsDetail = true
- // ) {
- // //
- // var result = GetDbSet (
- // containsDetail: containsDetail
- // );
-
- // //
- // // Handle Soft Deleted Items ...
- // if (ignoreSoftDeleteds) {
- // result = result.Where (x => x.Deleted == false);
- // }
-
- // //
- // if (request.First.HasValue) {
- // //
- // if (!request.After.IsNullOrEmpty ()) {
- // //
- // TKey lastId = XCursorHelper.FromCursor (request.After);
- // result = result.Where (x => GetKey (x).ToString() > lastId.ToString());
- // }
-
- // //
- // result = result.Take (request.First.Value);
- // }
-
- // //
- // // Apply Sorting ...
- // List nodes = null;
- // if (!request.SortBy.IsNullOrEmpty ()) {
- // nodes = result
- // .ApplySorting (
- // request.SortBy, !request.DescendingSort
- // ).ToList ();
- // }
-
- // //
- // // Claculate Required Info ...
- // int totalCount = result.CountAsync ().Result;
- // int maxId = nodes.Max (x => Convert.ToInt32 (GetKey (x)));
- // int minId = nodes.Min (x => Convert.ToInt32 (GetKey (x)));
- // bool hasNextPage = nodes.Any (x => Convert.ToInt32 (GetKey (x)) > maxId);
- // bool hasPreviousPage = nodes.Any (x => Convert.ToInt32 (GetKey (x)) < minId);
-
- // //
- // return Task.FromResult (new XPageResponse {
- // Nodes = nodes,
- // TotalCount = totalCount,
- // HasNextPage = hasNextPage,
- // HasPreviousPage = hasPreviousPage
- // });
- // }
-
- //
- // TODO: Fix this ...
- // public Task> RequestConditionalPageAsync (
- // Expression> condition,
- // XPageRequest request,
- // bool ignoreSoftDeleteds = true,
- // bool containsDetail = true
- // ) {
- // //
- // var result = GetDbSet (
- // containsDetail: containsDetail
- // )
- // .Where (condition);
-
- // //
- // // Handle Soft Deleted Items ...
- // if (ignoreSoftDeleteds) {
- // result = result.Where (x => x.Deleted == false);
- // }
-
- // //
- // if (request.First.HasValue) {
- // //
- // if (!request.After.IsNullOrEmpty ()) {
- // //
- // int lastId = XCursorHelper.FromCursor (request.After);
- // result = result.Where (x => Convert.ToInt32 (GetKey (x)) > lastId);
- // }
-
- // //
- // result = result.Take (request.First.Value);
- // }
-
- // //
- // // Apply Sorting ...
- // List nodes = null;
- // if (!request.SortBy.IsNullOrEmpty ()) {
- // nodes = result
- // .ApplySorting (
- // request.SortBy, !request.DescendingSort)
- // .ToList ();
- // }
-
- // //
- // // Claculate Required Info ...
- // int totalCount = result.CountAsync ().Result;
- // int maxId = nodes.Max (x => Convert.ToInt32 (GetKey (x)));
- // int minId = nodes.Min (x => Convert.ToInt32 (GetKey (x)));
- // bool hasNextPage = result.Any (x => Convert.ToInt32 (GetKey (x)) > maxId);
- // bool hasPreviousPage = result.Any (x => Convert.ToInt32 (GetKey (x)) < minId);
-
- // //
- // return Task.FromResult (new XPageResponse {
- // Nodes = nodes,
- // TotalCount = totalCount,
- // HasNextPage = hasNextPage,
- // HasPreviousPage = hasPreviousPage
- // });
- // }
- #endregion
-
- //
- #region Update ...
- public async Task UpdateAsync(
- TKey id,
- T item,
- bool saveChanges = true
- )
- {
- //
- // Get Exists Entity ...
- var existsEntity = await GetAsync(
- id,
- containsDetail: true,
- ignoreSoftDeleteds: false
- );
-
- //
- // 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();
-
- //
- // set isSucceed Value based on Changes ...
- isSucceed = qResult > 0;
- }
-
- //
- // Notify Event ...
- if (
- isSucceed &&
- !baseRepositoryEvents.IsNull()
- )
- {
- baseRepositoryEvents
- .UpdateEvent(new XBaseEventModel(entry.Entity));
- }
-
- //
- // Return result base on action Succeed ...
- return isSucceed ?
- entry.Entity :
- null;
- }
-
- public async Task UpdateRangeAsync(
- IEnumerable items,
- bool saveChanges = true
- )
- {
- //
- 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();
-
- //
- // set isSucceed Value based on Changes ...
- isSucceed = qResult > 0;
- }
-
- //
- // Notify Event ...
- if (
- isSucceed &&
- !baseRepositoryEvents.IsNull()
- )
- {
- baseRepositoryEvents
- .UpdateManyEvent(new XBaseEventModel>(null));
- }
-
- //
- // Return result base on action Succeed ...
- return isSucceed;
- }
- #endregion
-
//
#region Count ...
- public async Task CountAsync(bool ignoreSoftDeleteds = true)
+ ///
+ /// count all exists Entities ...
+ ///
+ ///
+ ///
+ ///
+ public async Task CountAsync(
+ bool ignoreSoftDeleteds = true,
+ CancellationToken cancellationToken = default
+ )
{
//
- var dbSet = GetDbSet();
+ var result = 0;
//
- if (ignoreSoftDeleteds && configuration.EnableSoftDelete)
+ if (ignoreSoftDeleteds)
{
- return await dbSet.CountAsync(i => i.Deleted == false);
+ //
+ result = await dbSet.CountAsync(
+ predicate: x => !x.Deleted,
+ cancellationToken: cancellationToken
+ );
}
else
{
- return await dbSet.CountAsync();
+ result = await dbSet.CountAsync(cancellationToken);
}
+
+ //
+ return result;
}
+ ///
+ /// count all exists Entities Pages by providing page size ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public async Task PagesCountAsync(
int pageSize,
- int? totalItems = null
+ int? totalItems = null,
+ bool ignoreSoftDeleteds = true,
+ CancellationToken cancellationToken = default
)
{
//
- int count = totalItems.HasValue ? totalItems.Value : await CountAsync();
+ int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
+ cancellationToken: cancellationToken,
+ ignoreSoftDeleteds: ignoreSoftDeleteds
+ );
int pagesCount = count / pageSize;
//
@@ -972,58 +561,371 @@ namespace xDataService.EFRepositories
#endregion
//
- #region Exists ...
- public async Task IsExistsAsync(
- TKey id,
- bool ignoreSoftDeleteds = true
+ #region Retrieve ...
+ ///
+ /// retrieve whole items as queryable ...
+ ///
+ /// a flag for Tracking behaviour
+ /// an Expression for Filter Items ...
+ /// an Order Builder expression for Ordering Query ...
+ /// an Include Builder expression for Including Navigation Properties ...
+ ///
+ public IQueryable AsQueryable(
+ bool asNoTracking = true,
+ Expression> predicate = null,
+ Func, IOrderedQueryable> orderBuilder = null,
+ Func, IIncludableQueryable> includeBuilder = null
)
{
//
- var result = await FindOneAsync(i =>
- GetKey(i)
- .ToString() == id
- .ToString(),
- ignoreSoftDeleteds: ignoreSoftDeleteds,
- containsDetail: false
- );
+ var result = dbSet
+ .AsQueryable();
//
- Detach(result);
+ // Apply Predicate ...
+ if (!predicate.IsNull())
+ {
+ result = result
+ .Where(predicate);
+ }
//
- return !result.IsNull();
+ // Apply Includes ...
+ if (!includeBuilder.IsNull())
+ {
+ result = includeBuilder(result);
+ }
+
+ //
+ // Apply Ordering ...
+ if (!orderBuilder.IsNull())
+ {
+ result = orderBuilder(result);
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// retrieve an Entity by it's Id ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task GetAsync(
+ TKey id,
+ bool ignoreSoftDeleteds = true,
+ Func, IIncludableQueryable> includeBuilder = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> 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;
+ }
+
+ ///
+ /// retrieve all exists Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> GetAllAsync(
+ bool ignoreSoftDeleteds = true,
+ Func, IOrderedQueryable> orderBuilder = null,
+ Func, IIncludableQueryable> includeBuilder = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> predicator = null;
+ if (ignoreSoftDeleteds)
+ {
+ predicator = x => !x.Deleted;
+ }
+ var result = await AsQueryable(
+ asNoTracking: true,
+ predicate: predicator,
+ orderBuilder: orderBuilder,
+ includeBuilder: includeBuilder
+ )
+ .ToListAsync(cancellationToken);
+
+ //
+ return result;
+ }
+
+ ///
+ /// retrieve all exists Entities
+ /// as Async Enumerable ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IAsyncEnumerable GetAllAsAsyncEnumerable(
+ bool ignoreSoftDeleteds = true,
+ Func, IOrderedQueryable> orderBuilder = null,
+ Func, IIncludableQueryable> includeBuilder = null
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> predicator = null;
+ if (ignoreSoftDeleteds)
+ {
+ predicator = x => !x.Deleted;
+ }
+ var result = AsQueryable(
+ asNoTracking: true,
+ predicate: predicator,
+ orderBuilder: orderBuilder,
+ includeBuilder: includeBuilder
+ )
+ .AsAsyncEnumerable();
+
+ //
+ return result;
+
+ }
+
+ ///
+ /// find an Entity by providing a Conditional Expression ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task FindOneAsync(
+ Expression> predicate,
+ bool ignoreSoftDeleteds = true,
+ Func, IIncludableQueryable> includeBuilder = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> 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;
+ }
+
+ ///
+ /// find a collection of Entities by proving a Conditional Expression ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> FindManyAsync(
+ Expression> predicate,
+ bool ignoreSoftDeleteds = true,
+ Func, IOrderedQueryable> orderBuilder = null,
+ Func, IIncludableQueryable> includeBuilder = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> 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;
+ }
+
+ ///
+ /// retrieve Entities based on XQuery Pagination structure ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> QueryAsync(
+ XQuery query,
+ bool ignoreSoftDeleteds = true,
+ Expression> predicate = null,
+ Func, IOrderedQueryable> orderBuilder = null,
+ Func, IIncludableQueryable> includeBuilder = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // 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
+ {
+ Page = query.Page,
+ Items = items.ToList(),
+ PageSize = query.PageSize,
+ TotalPages = totalPagesCount,
+ TotalItems = totalItemsCount,
+ TotalFilteredPages = filteredPagesCount,
+ TotalFilteredItems = filteredItemsCount
+ };
+
+ //
+ return result;
+ }
+ #endregion
+
+ //
+ #region Exists ...
+ ///
+ /// Check an Entity exists or not ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task IsExistsAsync(
+ TKey id,
+ bool ignoreSoftDeleteds = true,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //
+ // Prepare Ignore Soft Deleted Predicator ...
+ Expression> 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 ...
- public async Task SaveChangesAsync()
+ ///
+ /// Save all unsaved Transactions on DbContext ...
+ /// used fo Unit Of Works Design Pattern ...
+ ///
+ ///
+ ///
+ public async Task SaveChangesAsync(
+ CancellationToken cancellationToken = default
+ )
{
- return await unitOfWorks.SaveChangesAsync();
+ return await unitOfWorks.SaveChangesAsync(cancellationToken);
}
#endregion
//
- #region Keys ...
- 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);
- }
-
+ #region Key ...
+ ///
+ /// Retrieve Key of Entity ...
+ ///
+ ///
+ ///
public TKey GetKey(T item)
{
//
@@ -1058,7 +960,40 @@ namespace xDataService.EFRepositories
return keyString.FromJSON();
}
- public async Task HandleKeyAsync(T item)
+ ///
+ /// Set Key of Entity ...
+ ///
+ ///
+ ///
+ 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);
+ }
+
+ ///
+ /// Handle Checking Key ...
+ ///
+ ///
+ ///
+ ///
+ public async Task HandleKeyAsync(
+ T item,
+ CancellationToken cancellationToken = default
+ )
{
//
var keyType = typeof(TKey);
@@ -1088,6 +1023,10 @@ namespace xDataService.EFRepositories
//
#region Detach ...
+ ///
+ /// Detach an Entity ...
+ ///
+ ///
public void Detach(T item)
{
//
@@ -1100,6 +1039,10 @@ namespace xDataService.EFRepositories
Entry(item).State = EntityState.Detached;
}
+ ///
+ /// Detach an Enumerable of Entities ...
+ ///
+ ///
public void Detach(IEnumerable items)
{
//
@@ -1117,6 +1060,10 @@ namespace xDataService.EFRepositories
});
}
+ ///
+ /// Detach a Query Result of Entity ...
+ ///
+ ///
public void Detach(XQueryResult query)
{
//
@@ -1128,18 +1075,7 @@ namespace xDataService.EFRepositories
//
Detach(query.Items);
}
-
- public void Detach(XPageResponse page)
- {
- //
- if (page.IsNull() || !page.Nodes.HasChild())
- {
- return;
- }
-
- //
- Detach(page.Nodes);
- }
+ #endregion
#endregion
//
@@ -1163,25 +1099,10 @@ namespace xDataService.EFRepositories
{
return unitOfWorks.DbContext.Entry(item);
}
+ #endregion
- public IQueryable GetDbSet(
- bool containsDetail = false
- )
- {
- //
- IQueryable result = null;
- if (!containsDetail)
- {
- result = dbSet;
- }
- else
- {
- result = GetFullDbSet();
- }
-
- //
- return result;
- }
+ //
+ #region Private ...
#endregion
}
}
\ No newline at end of file
diff --git a/Extensions/XGraphQLExtensions.cs b/Extensions/XGraphQLExtensions.cs
index 8ca6de9..a6bccfb 100644
--- a/Extensions/XGraphQLExtensions.cs
+++ b/Extensions/XGraphQLExtensions.cs
@@ -13,10 +13,6 @@ namespace xDataService.Extensions {
return source.GetArgument (XGraphQLHelper.IgnoreSoftDeletedArgument.Name);
}
- public static bool GetContainsDetailArgument (this IResolveFieldContext source) {
- return source.GetArgument (XGraphQLHelper.ContainsDetailArgument.Name);
- }
-
public static string GetSearchQueryArgument (this IResolveFieldContext source) {
return source.GetArgument (XGraphQLHelper.SearchQueryArgument.Name);
}
diff --git a/GraphQL/XBaseGraphQLQuery.cs b/GraphQL/XBaseGraphQLQuery.cs
index 6c7ca14..06783f6 100644
--- a/GraphQL/XBaseGraphQLQuery.cs
+++ b/GraphQL/XBaseGraphQLQuery.cs
@@ -41,15 +41,14 @@ namespace xDataService.GraphQL {
name: helper.GetInQuerySingleName (),
arguments: new QueryArguments (
XGraphQLHelper.GetIdArgument (),
- XGraphQLHelper.IgnoreSoftDeletedArgument,
- XGraphQLHelper.ContainsDetailArgument
+ XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve : async context =>
await repository
- .GetAsync (
+ .GetAsync (
+ includeBuilder: null,
id: context.GetIdArgument (),
- ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument (),
- containsDetail: context.GetContainsDetailArgument ()
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
.ToDynamicObject ()
);
@@ -59,14 +58,14 @@ namespace xDataService.GraphQL {
FieldAsync> (
name: helper.GetInQueryCollectionName (),
arguments: new QueryArguments (
- XGraphQLHelper.IgnoreSoftDeletedArgument,
- XGraphQLHelper.ContainsDetailArgument
+ XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve : async context =>
await repository
.GetAllAsync (
- ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument (),
- containsDetail: context.GetContainsDetailArgument ()
+ orderBuilder: null,
+ includeBuilder: null,
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
.ToDynamicObject ()
);
@@ -77,8 +76,7 @@ namespace xDataService.GraphQL {
name: helper.GetFindOneName (),
arguments: new QueryArguments (
XGraphQLHelper.SearchQueryArgument,
- XGraphQLHelper.IgnoreSoftDeletedArgument,
- XGraphQLHelper.ContainsDetailArgument
+ XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve : async (context) => {
//
@@ -89,9 +87,9 @@ namespace xDataService.GraphQL {
//
return await repository
.FindOneAsync (
- whereClause: whereClase,
- ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument (),
- containsDetail: context.GetContainsDetailArgument ()
+ includeBuilder: null,
+ predicate: whereClase,
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
.ToDynamicObject ();
}
@@ -103,8 +101,7 @@ namespace xDataService.GraphQL {
name: helper.GetFindManyName (),
arguments: new QueryArguments (
XGraphQLHelper.SearchQueryArgument,
- XGraphQLHelper.IgnoreSoftDeletedArgument,
- XGraphQLHelper.ContainsDetailArgument
+ XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve : async (context) => {
//
@@ -115,9 +112,10 @@ namespace xDataService.GraphQL {
//
return await repository
.FindManyAsync (
- whereClause: whereClase,
- ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument (),
- containsDetail: context.GetContainsDetailArgument ()
+ orderBuilder: null,
+ includeBuilder: null,
+ predicate: whereClase,
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
.ToDynamicObject ();
}
@@ -134,6 +132,9 @@ namespace xDataService.GraphQL {
resolve : async context =>
await repository
.QueryAsync (
+ predicate: null,
+ orderBuilder: null,
+ includeBuilder: null,
query: context.GetQueryArgument (),
ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
@@ -144,9 +145,14 @@ namespace xDataService.GraphQL {
// Count ...
FieldAsync (
name: helper.GetCountName (),
+ arguments: new QueryArguments (
+ XGraphQLHelper.IgnoreSoftDeletedArgument
+ ),
resolve: async context =>
await repository
- .CountAsync ()
+ .CountAsync (
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
+ )
);
//
@@ -154,11 +160,13 @@ namespace xDataService.GraphQL {
FieldAsync (
name: helper.GetExistsName (),
arguments: new QueryArguments (
- XGraphQLHelper.GetIdArgument ()
+ XGraphQLHelper.GetIdArgument (),
+ XGraphQLHelper.IgnoreSoftDeletedArgument
),
resolve : async context =>
await repository.IsExistsAsync (
- context.GetIdArgument ()
+ id: context.GetIdArgument (),
+ ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument ()
)
);
#endregion
diff --git a/Helpers/XGraphQLHelper.cs b/Helpers/XGraphQLHelper.cs
index 7d7b2d9..51b3074 100644
--- a/Helpers/XGraphQLHelper.cs
+++ b/Helpers/XGraphQLHelper.cs
@@ -18,12 +18,6 @@ namespace xDataService.Constants {
Description = "determines result should ignore soft deleted items or not ..."
};
- public static QueryArgument ContainsDetailArgument = new QueryArgument {
- Name = "containsDetail",
- DefaultValue = false,
- Description = "determines result should contains navigation properties or not ..."
- };
-
public static QueryArgument SearchQueryArgument = new QueryArgument {
Name = "searchQuery",
Description = "the value which had to looking for ..."
diff --git a/InMemRepositories/XBaseInMemoryRepositoy.cs b/InMemRepositories/XBaseInMemoryRepositoy.cs
index 0e07f7e..c74d0da 100644
--- a/InMemRepositories/XBaseInMemoryRepositoy.cs
+++ b/InMemRepositories/XBaseInMemoryRepositoy.cs
@@ -3,16 +3,26 @@ 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.InMemRepositories
{
+ ///
+ /// a Base Repository Pattern Implementation Specially for InMemory Stores using
+ /// EF Core Capabilities ...
+ ///
+ ///
+ ///
public abstract class XBaseInMemoryRepositoy : IXBaseRepository
where TEntity : XBaseEntity
{
@@ -32,82 +42,169 @@ namespace xDataService.InMemRepositories
IXBaseRepositoryEvents baseRepositoryEvents = null
)
{
- this.configuration = configuration;
this.keyGenerator = keyGenerator;
+ this.configuration = configuration;
this.baseRepositoryEvents = baseRepositoryEvents;
}
#endregion
+ //
+ #region Actions ...
//
#region Add ...
- public async Task AddAsync(TEntity item, bool saveChanges = true)
+ ///
+ /// add a new Entity ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task AddAsync(
+ TEntity item,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
// Handle Key ...
- item = await HandleKeyAsync(item);
+ item = await HandleKeyAsync(
+ item: item,
+ cancellationToken: cancellationToken
+ );
+
+ //
+ var isSucceed = false;
//
// Add Item to Dictionary ...
- store[item.Id] = item;
+ try
+ {
+ //
+ store[item.Id] = item;
+ isSucceed = true;
+ }
+ catch
+ {
+ isSucceed = false;
+ }
+
+ //
+ // Notify Event ...
+ if (
+ isSucceed &&
+ !baseRepositoryEvents.IsNull()
+ )
+ {
+ //
+ baseRepositoryEvents
+ .AddEvent(new XBaseEventModel(item));
+ }
//
// Return Item ...
return item;
}
- public async Task AddOrUpdateAsync(TEntity item, bool saveChanges = true)
+ ///
+ /// add or update an Entity (add if not exists/update if exists) ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task AddOrUpdateAsync(
+ TEntity item,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
- var isExists = await IsExistsAsync(item.Id);
+ var isExists = await IsExistsAsync(
+ id: item.Id,
+ ignoreSoftDeleteds: true,
+ cancellationToken: cancellationToken
+ );
+
+ //
+ var isSucceed = false;
if (isExists)
{
- item = await UpdateAsync(item.Id, item);
+ //
+ try
+ {
+ //
+ item = await UpdateAsync(
+ item: item,
+ id: item.Id,
+ saveChanges: saveChanges,
+ cancellationToken: cancellationToken
+ );
+ isSucceed = true;
+ }
+ catch
+ {
+ isSucceed = false;
+ }
}
else
{
- item = await AddAsync(item);
+ //
+ 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(item));
+ }
+ else
+ {
+ //
+ baseRepositoryEvents
+ .AddEvent(new XBaseEventModel(item));
+ }
}
//
return item;
}
- public async Task AddRangeAsync(IEnumerable items, bool saveChanges = true)
- {
- //
- foreach (var item in items)
- {
- var handled = await HandleKeyAsync(item);
- store[handled.Id] = handled;
- }
- }
- #endregion
-
- //
- #region Remove ...
- public async Task RemoveAsync(TKey id, bool softDelete = true, bool saveChanges = true)
- {
- //
- var isExists = await IsExistsAsync(id);
- if (!isExists)
- {
- return null;
- }
-
- //
- var result = store[id];
- store.TryRemove(id, out _);
-
- //
- return result;
- }
-
- public async Task RemoveAsync(TEntity item, bool softDelete = true, bool saveChanges = true)
- {
- return await RemoveAsync(item.Id);
- }
-
- public async Task RemoveRangeAsync(IEnumerable items, bool softDelete = true, bool saveChanges = true)
+ ///
+ /// add a range of new Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task AddRangeAsync(
+ IEnumerable items,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
var isValid = !items.IsNull() && items.HasChild();
@@ -119,55 +216,589 @@ namespace xDataService.InMemRepositories
//
foreach (var item in items)
{
- await RemoveAsync(item);
+ //
+ await AddAsync(
+ item: item,
+ saveChanges: saveChanges,
+ cancellationToken: cancellationToken
+ );
+ }
+
+ //
+ // Notify Event ...
+ if (
+ isValid &&
+ !baseRepositoryEvents.IsNull()
+ )
+ {
+ //
+ baseRepositoryEvents
+ .AddManyEvent(new XBaseEventModel>(null));
}
}
#endregion
//
- #region Retrieve ...
- public IQueryable AsQueryable()
- {
- return store.Values.AsQueryable();
- }
-
- public async Task GetAsync(TKey id, bool ignoreSoftDeleteds = true, bool containsDetail = false)
+ #region Update ...
+ ///
+ /// Update an Entity values ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task UpdateAsync(
+ TKey id,
+ TEntity item,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
- var isExists = await IsExistsAsync(id);
+ var isExists = await IsExistsAsync(
+ id: id,
+ ignoreSoftDeleteds: true,
+ cancellationToken: cancellationToken
+ );
if (!isExists)
{
return null;
}
//
- return store[id];
+ var isSucceed = false;
+ var exists = store[id];
+
+ //
+ try
+ {
+ //
+ exists = exists.UpdateData(
+ exists,
+ propertyBlackList: new List { nameof(exists.Id) }
+ );
+ store[id] = exists;
+
+ //
+ isSucceed = true;
+ }
+ catch
+ {
+ isSucceed = false;
+ }
+
+ //
+ // Notify Event ...
+ if (
+ isSucceed &&
+ !baseRepositoryEvents.IsNull()
+ )
+ {
+ //
+ baseRepositoryEvents
+ .UpdateEvent(new XBaseEventModel(item));
+ }
+
+ //
+ return exists;
}
- public async Task> GetAllAsync(bool ignoreSoftDeleteds = true, bool containsDetail = false)
+ ///
+ /// Update a range of Entities ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task UpdateRangeAsync(
+ IEnumerable items,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
- var result = store.Values.AsEnumerable();
- return await Task.FromResult(result);
- }
+ var result = false;
+ var isValid = !items.IsNull() && items.HasChild();
+ if (!isValid)
+ {
+ return result;
+ }
- public async Task FindOneAsync(Expression> whereClause, bool ignoreSoftDeleteds = true, bool containsDetail = false)
+ //
+ 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 ...
+ ///
+ /// remove an Entity by it's Id ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task RemoveAsync(
+ TKey id,
+ bool softDelete = true,
+ bool saveChanges = true,
+ CancellationToken cancellationToken = default
+ )
{
//
- var func = whereClause.Compile();
- var result = store.Values.FirstOrDefault(x => func(x));
- return await Task.FromResult(result);
+ 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;
}
- public async Task