Initial Commit ...
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# DotNet ...
|
||||
bin
|
||||
obj
|
||||
|
||||
#
|
||||
# Natural Docs ...
|
||||
Documentation/*
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using xCommons.Extensions;
|
||||
using xExceptions.Constants;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// a Base class which carry required things as a Father for it's childs ...
|
||||
/// </summary>
|
||||
public abstract class XBaseClass {
|
||||
//
|
||||
#region Properties ...
|
||||
/// <summary>
|
||||
/// LogTag which Specified for this class ...
|
||||
/// </summary>
|
||||
private readonly string LOG_TAG;
|
||||
|
||||
/// <summary>
|
||||
/// logger instance ...
|
||||
/// </summary>
|
||||
private readonly ILogger logger;
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Constructor ...
|
||||
public XBaseClass (ILoggerFactory loggerFactory) {
|
||||
//
|
||||
// Preparing Log Tag ...
|
||||
LOG_TAG = this.GetType ().Name;
|
||||
|
||||
//
|
||||
Type classType = this.GetType ();
|
||||
logger = loggerFactory.CreateLogger (classType);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Protected ...
|
||||
/// <summary>
|
||||
/// Extract Prepared Log MEssage ...
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual string GetLogMessage (string message) {
|
||||
//
|
||||
// Prepare Log Message ...
|
||||
message = $"{LOG_TAG} => {message}";
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logging specific Message ...
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="logLevel"></param>
|
||||
protected virtual void LogMessage (
|
||||
string message,
|
||||
LogLevel logLevel = LogLevel.Information
|
||||
) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (message.IsNullOrEmpty ()) {
|
||||
throw XException.InvalidArgs
|
||||
.ToException ();
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare Log Message ...
|
||||
message = GetLogMessage (message);
|
||||
|
||||
//
|
||||
// Logging Message ...
|
||||
logger.Log (
|
||||
message: message,
|
||||
logLevel: logLevel
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logging specific Message to Console ...
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
protected virtual void ConsoleMessage (string message) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (message.IsNullOrEmpty ()) {
|
||||
throw XException.InvalidArgs
|
||||
.ToException ();
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare Log Message ...
|
||||
message = GetLogMessage (message);
|
||||
|
||||
//
|
||||
// Logging Message ...
|
||||
Console.WriteLine (message);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// Descriptors classes Map required data for creating Entities on Seeding time ...
|
||||
/// this is a Base Descriptor class ...
|
||||
/// </summary>
|
||||
public abstract class XBaseDescriptor { }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// DTO - Data Transfer Objects is a kind of classes which Represent Entities ...
|
||||
/// this is base Dto class ...
|
||||
/// </summary>
|
||||
public abstract class XBaseDto { }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// Base Entity Class
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class XBaseEntity<T> {
|
||||
/// <summary>
|
||||
/// Entity Id
|
||||
/// </summary>
|
||||
/// <value>entity unique id</value>
|
||||
[Key]
|
||||
[Required]
|
||||
public T Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provided Soft Delete Behaviour ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public bool Deleted { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// a BaseEntity Class which has Id of Guid type
|
||||
/// </summary>
|
||||
public class XBaseGuidIDEntity : XBaseEntity<Guid> { }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// a BaseEntity Class which has Id of int type
|
||||
/// </summary>
|
||||
public abstract class XBaseIntIDEntity : XBaseEntity<int> { }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// Range Request Classes Carry a List of Objects
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class XBaseRangeRequest<T> {
|
||||
public IEnumerable<T> Items { get; set; } = new HashSet<T> ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace xModels.Base {
|
||||
public abstract class XBaseStorableDto<TKey> : XBaseDto {
|
||||
public abstract TKey Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace xModels.Base {
|
||||
/// <summary>
|
||||
/// a BaseEntity Class which has Id of string type
|
||||
/// </summary>
|
||||
public class XBaseStringIDEntity : XBaseEntity<string> { }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using xCommons.Constants;
|
||||
using xModels.Base;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
public class XDeviceDto : XBaseDto {
|
||||
/// <summary>
|
||||
/// Operating System
|
||||
/// </summary>
|
||||
/// <value>device operating system identifier</value>
|
||||
public string Os { get; set; }
|
||||
/// <summary>
|
||||
/// Operating System Version
|
||||
/// </summary>
|
||||
/// <value>which version of operatin system is in use</value>
|
||||
public string OsVersion { get; set; }
|
||||
/// <summary>
|
||||
/// Device Browser
|
||||
/// </summary>
|
||||
/// <value>the Browser identifier</value>
|
||||
public string Browser { get; set; }
|
||||
/// <summary>
|
||||
/// Browser Engine Agent
|
||||
/// </summary>
|
||||
/// <value>browser engine Agent</value>
|
||||
public string UserAgent { get; set; }
|
||||
/// <summary>
|
||||
/// Type of client Device
|
||||
/// </summary>
|
||||
/// <value>represent device type <see>XDeviceType</see></value>
|
||||
public XDeviceType DeviceType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using xCommons.Constants;
|
||||
using xModels.Base;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
public partial class XFileDto : XBaseDto {
|
||||
[Required]
|
||||
public string AuthorId { get; set; }
|
||||
|
||||
public XFileType Type { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength (255)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[StringLength (255)]
|
||||
public string Thumb { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength (255)]
|
||||
public string Path { get; set; }
|
||||
|
||||
[StringLength (255)]
|
||||
public string ThumbPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime UploadedOn { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// Some Requests Get Object Response Result of Data ...
|
||||
/// </summary>
|
||||
public struct XObjectResponseResult<T> {
|
||||
|
||||
public XObjectResponseResult (T responseObject, string responseText) {
|
||||
this.Object = responseObject;
|
||||
this.Text = responseText;
|
||||
}
|
||||
|
||||
public T Object { get; }
|
||||
|
||||
public string Text { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// Request a Page of Data based on Cursor ...
|
||||
/// this only be Used in GraphQL ...
|
||||
/// </summary>
|
||||
public class XPageRequest {
|
||||
public int? First { get; set; }
|
||||
public int? Last { get; set; }
|
||||
public string After { get; set; } = "";
|
||||
public string Before { get; set; } = "";
|
||||
public string SortBy { get; set; } = "";
|
||||
public bool DescendingSort { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// Result of a Requested Page of Data based on Cursor ...
|
||||
/// this only be Used in GraphQL ...
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class XPageResponse<T> {
|
||||
public List<T> Nodes { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
public bool HasNextPage { get; set; }
|
||||
public bool HasPreviousPage { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using xModels.Base;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// Request a Page of Data Based on Query ...
|
||||
/// this can used in every Data Providers ...
|
||||
/// </summary>
|
||||
public class XQuery : XBaseDto {
|
||||
/// <summary>
|
||||
/// an string for filtering results
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Filter { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// determines fully load object with it's relational fields or not
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public bool ContainsDetail { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// specifiy sorting of items
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string SortBy { get; set; } = nameof (XBaseIntIDEntity.Id);
|
||||
|
||||
/// <summary>
|
||||
/// specify sorting direction
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public bool IsAscending { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// specify page number
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public int Page { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// specify page size
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public int PageSize { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using xModels.Base;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// Result of a Requested Page of Data Based on Query ...
|
||||
/// this can used in every Data Providers ...
|
||||
/// </summary>
|
||||
public class XQueryResult<T> : XBaseDto {
|
||||
/// <summary>
|
||||
/// a collection of items for a page ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public IEnumerable<T> Items { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current Page Number ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public long Page { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current Page Size ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public long PageSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total Pages ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public long TotalPages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total Filtered Items ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public long TotalFilteredItems { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total Exists Items ...
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public long TotalItems { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace xModels.Dtos {
|
||||
/// <summary>
|
||||
/// in some cases we have to validate a revision of request, this is a model
|
||||
/// which used to request a revision validator ...
|
||||
/// </summary>
|
||||
public class XValidateRevisionRequest {
|
||||
[Required]
|
||||
public string Revision { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using xCommons.Extensions;
|
||||
using xExceptions.Constants;
|
||||
using xModels.Base;
|
||||
using xModels.Interfaces;
|
||||
|
||||
namespace xModels.Extensions {
|
||||
public static class DIExtensions {
|
||||
/// <summary>
|
||||
/// Register an Specific Store in DI ...
|
||||
/// </summary>
|
||||
/// <param name="services">DI service collection ...</param>
|
||||
/// <param name="store">an implementation of inetrface of store ...</param>
|
||||
/// <param name="lifeTime">service lifetime</param>
|
||||
/// <typeparam name="TImplementation">implementation of TType ...</typeparam>
|
||||
/// <typeparam name="TType">an inetrface which implements IXBaseStore<TStoreItemDto, TKey></typeparam>
|
||||
/// <typeparam name="TStoreItemDto">type of an instance of XBaseStorable<TKey></typeparam>
|
||||
/// <typeparam name="TKey">type of key of StorableItem</typeparam>
|
||||
/// <returns></returns>
|
||||
public static void AddXStore<TImplementation, TType, TStoreItemDto, TKey> (
|
||||
this IServiceCollection services,
|
||||
TImplementation store,
|
||||
ServiceLifetime lifeTime = ServiceLifetime.Singleton
|
||||
)
|
||||
where TImplementation : TType
|
||||
where TType : IXBaseStore<TStoreItemDto, TKey>
|
||||
where TStoreItemDto : XBaseStorableDto<TKey> {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (store.IsNull ()) {
|
||||
throw XException.InvalidArgs
|
||||
.ToException ();
|
||||
}
|
||||
|
||||
//
|
||||
// Register Service in DI ...
|
||||
services.Add (new ServiceDescriptor (typeof (TType), typeof (TImplementation), lifeTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace xModels.Interfaces {
|
||||
/// <summary>
|
||||
/// Some times we need to wrap Entities by some logs or audits ...
|
||||
/// this class provide Audit fields for an Auditable Entity ...
|
||||
/// </summary>
|
||||
public interface IXAuditable {
|
||||
string UserAgent { get; }
|
||||
string UserIp { get; }
|
||||
DateTime TransactionTime { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using xModels.Base;
|
||||
|
||||
namespace xModels.Interfaces {
|
||||
public interface IXBaseStore<T, TKey> where T : XBaseStorableDto<TKey> {
|
||||
//
|
||||
#region Retrieve ...
|
||||
/// <summary>
|
||||
/// Retrieve all Exists Items ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<T>> GetAll ();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve specific Item by key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
Task<T> Get (TKey key);
|
||||
|
||||
/// <summary>
|
||||
/// retrieve items based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<T>> FindMany (Expression<Func<T, bool>> condition);
|
||||
|
||||
/// <summary>
|
||||
/// retrieve item based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
Task<T> FindOne (Expression<Func<T, bool>> condition);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Add ...
|
||||
/// <summary>
|
||||
/// add specific item to Store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> Add (T item);
|
||||
|
||||
/// <summary>
|
||||
/// Add a Collection of Items on Store ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> AddMany (XBaseRangeRequest<T> items);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Remove ...
|
||||
/// <summary>
|
||||
/// Remove an item from store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> Remove (T item);
|
||||
|
||||
/// <summary>
|
||||
/// remove an item by it's Key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> RemoveByKey (TKey key);
|
||||
|
||||
/// <summary>
|
||||
/// remove a collection of items at once ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> RemoveMany(XBaseRangeRequest<T> items);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Update ...
|
||||
/// <summary>
|
||||
/// Update Exists Item in store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="propertyWhiteList"></param>
|
||||
/// <param name="propertyBlackList"></param>
|
||||
/// <param name="propertyValueProviders"></param>
|
||||
/// <param name="updateWithNullOrEmptyValues"></param>
|
||||
/// <returns></returns>
|
||||
Task<T> Update (
|
||||
T item,
|
||||
ICollection<string> propertyWhiteList = null,
|
||||
ICollection<string> propertyBlackList = null,
|
||||
ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
|
||||
bool updateWithNullOrEmptyValues = false
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Update a Collection of Exists Items ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="propertyWhiteList"></param>
|
||||
/// <param name="propertyBlackList"></param>
|
||||
/// <param name="propertyValueProviders"></param>
|
||||
/// <param name="updateWithNullOrEmptyValues"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> UpdateMany (
|
||||
XBaseRangeRequest<T> items,
|
||||
ICollection<string> propertyWhiteList = null,
|
||||
ICollection<string> propertyBlackList = null,
|
||||
ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
|
||||
bool updateWithNullOrEmptyValues = false
|
||||
);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Exists ...
|
||||
/// <summary>
|
||||
/// retrieve item(s) exists based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> IsExists (Expression<Func<T, bool>> condition);
|
||||
|
||||
/// <summary>
|
||||
/// is exists an item by providing it's key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> IsExistsByKey (TKey key);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Count ...
|
||||
/// <summary>
|
||||
/// Count Exists items ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<int> Count ();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using xModels.Base;
|
||||
using xModels.Dtos;
|
||||
|
||||
namespace xModels.Interfaces {
|
||||
public interface IXEntityControllerActions<TEntity, TKey>
|
||||
where TEntity : XBaseEntity<TKey> {
|
||||
//
|
||||
#region Retrieve ...
|
||||
Task<ActionResult<TEntity>> Get (
|
||||
[FromRoute] TKey id, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
|
||||
);
|
||||
|
||||
Task<ActionResult<IEnumerable<TEntity>>> GetAll (
|
||||
[FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
|
||||
);
|
||||
|
||||
Task<ActionResult<TEntity>> FindOne (
|
||||
[FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
|
||||
);
|
||||
|
||||
Task<ActionResult<IEnumerable<TEntity>>> FindMany (
|
||||
[FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
|
||||
);
|
||||
|
||||
Task<ActionResult<XQueryResult<TEntity>>> Query (
|
||||
[FromQuery] XQuery query, [FromQuery] bool ignoreSoftDeleteds = true
|
||||
);
|
||||
|
||||
//
|
||||
// TODO: Fix this ...
|
||||
// Task<ActionResult<XPageResponse<TEntity>>> RequestPage (
|
||||
// [FromQuery] XPageRequest request, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
|
||||
// );
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Add ...
|
||||
Task<ActionResult<TEntity>> Add (TEntity item);
|
||||
|
||||
Task<ActionResult<TEntity>> AddOrUpdate (TEntity item);
|
||||
|
||||
Task<ActionResult> AddMany (XBaseRangeRequest<TEntity> request);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Update ...
|
||||
Task<ActionResult<TEntity>> Update (
|
||||
[FromRoute] TKey id, [FromBody] TEntity item
|
||||
);
|
||||
|
||||
Task<ActionResult<bool>> UpdateMany (
|
||||
XBaseRangeRequest<TEntity> request
|
||||
);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Exists ...
|
||||
Task<ActionResult<bool>> IsExists (
|
||||
[FromRoute] TKey id,
|
||||
bool ignoreSoftDeletedss = true
|
||||
);
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Remove ...
|
||||
Task<ActionResult<TEntity>> Remove (
|
||||
[FromRoute] TKey id,
|
||||
bool softDelete = true
|
||||
);
|
||||
|
||||
Task<ActionResult> RemoveMany (
|
||||
XBaseRangeRequest<TEntity> request,
|
||||
bool softDelete = true
|
||||
);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using xCommons.Extensions;
|
||||
using xModels.Base;
|
||||
using xModels.Interfaces;
|
||||
|
||||
namespace xModels.Providers {
|
||||
public abstract class XBaseInMemoryStore<T, TKey> : IXBaseStore<T, TKey>
|
||||
where T : XBaseStorableDto<TKey> {
|
||||
/// <summary>
|
||||
/// this is main store of items ...
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
private static ConcurrentBag<T> STORE = new ConcurrentBag<T> ();
|
||||
|
||||
//
|
||||
#region Retrieve ...
|
||||
/// <summary>
|
||||
/// Retrieve all Exists Items ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<IEnumerable<T>> GetAll () {
|
||||
//
|
||||
var result = STORE.AsEnumerable ();
|
||||
return Task.FromResult (result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve specific Item by key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<T> Get (TKey key) {
|
||||
//
|
||||
return IsExistsByKey (key)
|
||||
.ContinueWith (isExistsTask => {
|
||||
//
|
||||
var isExists = isExistsTask
|
||||
.RunTask ();
|
||||
|
||||
//
|
||||
if (!isExists) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
var result = STORE
|
||||
.FirstOrDefault (i => GetKey (i).Equals (key));
|
||||
return result;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieve items based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
public Task<IEnumerable<T>> FindMany (Expression<Func<T, bool>> condition) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (condition.IsNull ()) {
|
||||
return Task.FromResult (new List<T> ().AsEnumerable ());
|
||||
}
|
||||
|
||||
//
|
||||
var whereFunc = condition.Compile ();
|
||||
var result = STORE.Where (whereFunc);
|
||||
|
||||
//
|
||||
return Task.FromResult (result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieve item based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
public Task<T> FindOne (Expression<Func<T, bool>> condition) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (condition.IsNull ()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
var whereFunc = condition.Compile ();
|
||||
var result = STORE.FirstOrDefault (whereFunc);
|
||||
|
||||
//
|
||||
return Task.FromResult (result);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Add ...
|
||||
/// <summary>
|
||||
/// add specific item to Store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> Add (T item) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (item.IsNull () || GetKey (item).IsNull ()) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Try to add item ...
|
||||
return IsExistsByKey (GetKey (item))
|
||||
.ContinueWith (isExistsTask => {
|
||||
//
|
||||
// Check item exists in Store or not ...
|
||||
var isExists = isExistsTask.RunTask ();
|
||||
if (isExists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Add Item to Store ...
|
||||
STORE.Add (item);
|
||||
|
||||
//
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a Collection of Items on Store ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> AddMany (XBaseRangeRequest<T> items) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
items.IsNull () ||
|
||||
!items.Items.HasChild ()
|
||||
) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Must Add Items ...
|
||||
var mustAddItems = items.Items
|
||||
.Where (i => !GetKey (i)
|
||||
.IsNull () && !STORE
|
||||
.Any (si => GetKey (i).Equals (GetKey (si)))
|
||||
);
|
||||
if (!mustAddItems.HasChild ()) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Add Items ...
|
||||
try {
|
||||
//
|
||||
mustAddItems
|
||||
.ToList ()
|
||||
.ForEach (mi => STORE.Add (mi));
|
||||
|
||||
//
|
||||
return Task.FromResult (true);
|
||||
} catch {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Remove ...
|
||||
/// <summary>
|
||||
/// Remove an item from store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> Remove (T item) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
item.IsNull () ||
|
||||
!STORE
|
||||
.Any (i => GetKey (i)
|
||||
.Equals (GetKey (item)))
|
||||
) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
RemoveItemFromStore (item);
|
||||
return Task.FromResult (true);
|
||||
} catch {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// remove an item by it's Key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> RemoveByKey (TKey key) {
|
||||
return Get (key)
|
||||
.ContinueWith (getTask => {
|
||||
//
|
||||
// retrieve item by it's Key ...
|
||||
var item = getTask
|
||||
.RunTask ();
|
||||
|
||||
//
|
||||
// Check item exists ...
|
||||
if (item.IsNull ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to remove item ...
|
||||
var result = false;
|
||||
try {
|
||||
//
|
||||
result = Remove (item)
|
||||
.RunTask ();
|
||||
} catch {
|
||||
result = false;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// remove a collection of items at once ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> RemoveMany (XBaseRangeRequest<T> items) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
items.IsNull () ||
|
||||
!items.Items.HasChild ()
|
||||
) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
var mustRemovedItems = items.Items
|
||||
.Where (i => STORE
|
||||
.Any (si => GetKey (si).Equals (GetKey (i)))
|
||||
);
|
||||
if (!mustRemovedItems.HasChild ()) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
RemoveItemsFromStore (mustRemovedItems);
|
||||
return Task.FromResult (true);
|
||||
} catch {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Update ...
|
||||
/// <summary>
|
||||
/// Update Exists Item in store ...
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="propertyWhiteList"></param>
|
||||
/// <param name="propertyBlackList"></param>
|
||||
/// <param name="propertyValueProviders"></param>
|
||||
/// <param name="updateWithNullOrEmptyValues"></param>
|
||||
/// <returns></returns>
|
||||
public Task<T> Update (
|
||||
T item,
|
||||
ICollection<string> propertyWhiteList = null,
|
||||
ICollection<string> propertyBlackList = null,
|
||||
ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
|
||||
bool updateWithNullOrEmptyValues = false
|
||||
) {
|
||||
return Get (GetKey (item))
|
||||
.ContinueWith (getTask => {
|
||||
//
|
||||
var existsItem = getTask
|
||||
.RunTask ();
|
||||
|
||||
//
|
||||
// Validate item Exists ...
|
||||
if (existsItem.IsNull ()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
var updatedItem = existsItem;
|
||||
updatedItem.UpdateData (
|
||||
updateWith: item,
|
||||
propertyWhiteList: propertyWhiteList,
|
||||
propertyBlackList: propertyBlackList,
|
||||
propertyValueProviders: propertyValueProviders,
|
||||
updateWithNullOrEmptyValues: updateWithNullOrEmptyValues,
|
||||
throwExceptionOnFails: true
|
||||
);
|
||||
|
||||
//
|
||||
RemoveItemFromStore (existsItem);
|
||||
STORE.Add (updatedItem);
|
||||
|
||||
//
|
||||
return updatedItem;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a Collection of Exists Items ...
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="propertyWhiteList"></param>
|
||||
/// <param name="propertyBlackList"></param>
|
||||
/// <param name="propertyValueProviders"></param>
|
||||
/// <param name="updateWithNullOrEmptyValues"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> UpdateMany (
|
||||
XBaseRangeRequest<T> items,
|
||||
ICollection<string> propertyWhiteList = null,
|
||||
ICollection<string> propertyBlackList = null,
|
||||
ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
|
||||
bool updateWithNullOrEmptyValues = false
|
||||
) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
items.IsNull () ||
|
||||
!items.Items.HasChild ()
|
||||
) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
// retrieve must updated items ...
|
||||
var mustUpdateItems = items
|
||||
.Items
|
||||
.Where (i => STORE
|
||||
.Any (
|
||||
si => GetKey (i).Equals (GetKey (si)))
|
||||
);
|
||||
if (!mustUpdateItems.HasChild ()) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Do Tasks ...
|
||||
var mustUpdateTasks = mustUpdateItems.Select (i => Update (
|
||||
i,
|
||||
propertyWhiteList : propertyWhiteList,
|
||||
propertyBlackList : propertyBlackList,
|
||||
propertyValueProviders : propertyValueProviders,
|
||||
updateWithNullOrEmptyValues : updateWithNullOrEmptyValues
|
||||
));
|
||||
return Task.WhenAll (mustUpdateTasks)
|
||||
.ContinueWith (updateTasks => {
|
||||
//
|
||||
var updatedItems = updateTasks
|
||||
.RunTask ();
|
||||
|
||||
//
|
||||
if (!updatedItems.HasChild ()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Exists ...
|
||||
/// <summary>
|
||||
/// retrieve item(s) exists based on specific condition ...
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> IsExists (Expression<Func<T, bool>> condition) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (condition.IsNull ()) {
|
||||
return Task.FromResult (false);
|
||||
}
|
||||
|
||||
//
|
||||
var whereFunc = condition.Compile ();
|
||||
var result = STORE.Any (whereFunc);
|
||||
|
||||
//
|
||||
return Task.FromResult (result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// is exists an item by providing it's key ...
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> IsExistsByKey (TKey key) {
|
||||
return Task.Run (() => {
|
||||
return STORE.Any (i => GetKey (i).Equals (key));
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Count ...
|
||||
/// <summary>
|
||||
/// Count Exists items ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<int> Count () {
|
||||
//
|
||||
var result = STORE.Count ();
|
||||
return Task.FromResult (result);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Keys ...
|
||||
/// <summary>
|
||||
/// set Object Key ...
|
||||
/// </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>
|
||||
/// Get Object Key ...
|
||||
/// </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;
|
||||
}
|
||||
|
||||
//
|
||||
TKey result;
|
||||
try {
|
||||
result = keyString.FromJSON<TKey> ();
|
||||
} catch {
|
||||
result = keyString.ConvertTo<TKey> ();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//
|
||||
#region Private ...
|
||||
private void RemoveItemFromStore (T item) {
|
||||
STORE = new ConcurrentBag<T> (
|
||||
STORE.Except (new [] { item })
|
||||
);
|
||||
}
|
||||
|
||||
private void RemoveItemsFromStore (IEnumerable<T> items) {
|
||||
STORE = new ConcurrentBag<T> (
|
||||
STORE.Except (items)
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# xModels
|
||||
|
||||
it is a Part of XProject on SaherElm IT Center which provides:
|
||||
|
||||
- DTO Models.
|
||||
- Entity Models.
|
||||
- Navigation Models.
|
||||
- Configuration Models.
|
||||
- Some extra Extensions on Models.
|
||||
- etc.
|
||||
|
||||
this module has following dependencies :
|
||||
|
||||
- xCommons
|
||||
|
||||
there is no need any Configuration for this module.
|
||||
|
||||
## Maintainer
|
||||
|
||||
Hadi Khazaee asl
|
||||
|
||||
[https://www.saherelm.ir](https://www.saherelm.ir)
|
||||
|
||||
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="liget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Runtime Definition -->
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>xDashboard.xModels</PackageId>
|
||||
<Version>1.0.0</Version>
|
||||
<Authors>Hadi Khazaee Asl</Authors>
|
||||
<Company>SaherElm IT Center</Company>
|
||||
<Description>
|
||||
provide required models and related tools for using in xDashboard project.
|
||||
</Description>
|
||||
|
||||
<!-- Icon Definition -->
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Icon Handling -->
|
||||
<ItemGroup>
|
||||
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Local Modules -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xDashboard.xCommons" Version="1.0.0" />
|
||||
<!-- <ProjectReference Include="../xCommons/xCommons.csproj" /> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user