
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Configurations\Entities\XTagEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xTagService.Models.Entities;

namespace xTagService.Configurations.Entities
{
    public class XTagEntityConfiguration : XBaseEntityTypeConfiguration<XTag, int>
    {
        public override void Configure(EntityTypeBuilder<XTag> builder)
        {
            builder.ToTable("Tags");
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Constants\XTagServiceConstants.cs

namespace xTagService.Constants
{
    public struct XTagServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XTagServiceDILogTag = "XTagService";

        //
        // Table Mapping Identifiers ...
        public const string XTagTable = "Tags";

        //
        // GraphQL Collection Mappings ...
        public const string XTagSingleName = "tag";
        public const string XTagCollectionName = "tags";

        //
        // Hubs ...
        public const string XTagDtoHub = "tagDto";
        public const string XTagEntityHub = "tagEntity";

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ... 
        public const string GetXTagEFRepositoryDescriptor = "GetXTagEFRepositoryDescriptor";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XBaseProvidedHasTagControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;

namespace xTagService.Controllers
{
    [AllowAnonymous]
    public abstract class XBaseProvidedHasTagControllerBase<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXBaseProvidedHasTagController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly IXBaseProvided<TEntity, TDto, TKey, THub> provider;
        private readonly IXTagProvided<TEntity, TDto, TKey, THub> tagProvided;
        private readonly Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder;
        private readonly Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder;

        protected XBaseProvidedHasTagControllerBase(
            ILogger<XBaseProvidedHasTagControllerBase<TEntity, TDto, TKey, THub>> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXBaseProvided<TEntity, TDto, TKey, THub> provider,
            IXTagProvided<TEntity, TDto, TKey, THub> tagProvided,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.provider = provider;
            this.tagProvided = tagProvided;
            this.defaultOrderBuilder = defaultOrderBuilder;
            this.defaultIncludeBuilder = defaultIncludeBuilder;
        }

        //
        #region Provided ...
        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(id);

                //
                var result = await provider.Get(
                    id: id,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetAll(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/One")]
        public virtual async Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindOne(
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find a collection of Items by proving a Query Search ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/Many")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindMany(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.Query(
                    query: query,
                    predicate: null,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Owned Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query/Owned")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();

                //
                var result = await provider.QueryOwned(
                    query: query,
                    predicate: null,
                    userInfo: userInfo,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Add/Update/Remove ...
        /// <summary>
        /// Add an item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        public virtual async Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Update(
                    id: id,
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    id: id,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
        #endregion

        //
        #region Tag ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        public virtual async Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        public virtual async Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .DetachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        public virtual async Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tags)
                    .AddNotZeroChilds(tags.Items)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTags(
                        id: id,
                        tags: tags.Items,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        public virtual async Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                if (!tags.IsNull())
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            tags: tags.Items,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }
                else
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await tagProvided.GetTags(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagProvidedControllerBase.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xPushService.Base;
using xTagService.Interfaces;

namespace xTagService.Controllers
{
    public abstract class XTagProvidedControllerBase<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly IXTagProvided<TEntity, TDto, TKey, THub> tagProvided;

        protected XTagProvidedControllerBase(
            ILogger<XTagProvidedControllerBase<TEntity, TDto, TKey, THub>> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXIdentityProvider identityProvider,
            IXTagProvided<TEntity, TDto, TKey, THub> tagProvided
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.tagProvided = tagProvided;
        }

        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        public virtual async Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        public virtual async Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .DetachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        public virtual async Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tags)
                    .AddNotZeroChilds(tags.Items)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTags(
                        id: id,
                        tags: tags.Items,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        public virtual async Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                if (!tags.IsNull())
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            tags: tags.Items,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }
                else
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await tagProvided.GetTags(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xTagService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Controllers
{
    public abstract class XTagProviderControllerBase : XBaseProvidedController<XTag, XTagDto, int, XTagDtoHub>, IXTagProviderController
    {
        protected XTagProviderControllerBase(
            ILogger<XTagProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTagProvider provider,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagRepositoryControllerBase : XBaseRepositoryController<XTag, int>, IXBaseRepositoryController<XTag, int>
    {
        protected XTagRepositoryControllerBase(
            ILogger<XTagRepositoryControllerBase> logger, 
            XAppConfiguration appConfiguration, 
            XValidationProvider validationProvider, 
            IXTagRepository repository, 
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null, 
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            validationProvider, 
            repository, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagRepositoryProviderControllerBase : XBaseRepositoryProviderController<XTag, int, XTagEntityHub>, IXBaseRepositoryProviderController<XTag, int, XTagEntityHub>
    {
        protected XTagRepositoryProviderControllerBase(
            ILogger<XTagRepositoryProviderControllerBase> logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider, 
            IXTagRepositoryProvider provider, 
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null, 
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider, 
            provider, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagServiceControllerBase : XBaseServiceController<XTag, XTagDto, int>, IXBaseServiceController<XTag, XTagDto, int>
    {
        protected XTagServiceControllerBase(
            ILogger<XTagServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXTagRepositoryService repositoryService,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagServiceProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Controllers
{
    public abstract class XTagServiceProviderControllerBase : XBaseServiceProviderController<XTag, XTagDto, int, XTagDtoHub>, IXBaseServiceProviderController<XTag, XTagDto, int, XTagDtoHub>
    {
        protected XTagServiceProviderControllerBase(
            ILogger<XTagServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTagServiceProvider provider,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xTagService.Constants;
using xTagService.Helpers;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Interfaces.Entities;
using xTagService.Providers;
using xTagService.Providers.Dtos;
using xTagService.Providers.Entities;

namespace xTagService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXTagService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddTagService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXTagService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddTagService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XTagService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXTagService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region  Using XTag Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XTagDtoHub>(XTagServiceConstants.XTagDtoHub);
            pushHelper.AddHub<XTagEntityHub>(XTagServiceConstants.XTagEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XTag Repository Descriptor ...
            if (!descriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: descriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor descriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XTagServiceConstants.XTagServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddTagService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    descriptor = typeof(XTagServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XTagServiceConstants.GetXTagEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    descriptor = XTagServiceHelper.GetXTagMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    descriptor = XTagServiceHelper.GetXTagInMemoryRepositoryDescriptor();
                    break;
            }

            //
            // Register XTag Repository Descriptor ...
            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: descriptor
            );

            //
            // Register Dto Services ...
            services.Add(
                new ServiceDescriptor(typeof(IXTagServiceProvider), typeof(XTagServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXTagRepositoryService), typeof(XTagRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXTagRepositoryProvider), typeof(XTagRepositoryProvider), lifeTime)
            );

            //
            services.Add(
                new ServiceDescriptor(typeof(IXTagProvider), typeof(XTagProvider), lifeTime)
            );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XTag source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XTagDto source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XTag UpdateReferences(
            this XTag source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XTag result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XTagDto UpdateReferences(
            this XTagDto source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XTagDto result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Helpers\XTagServiceHelper.cs

using GraphQL.Types;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;
using xTagService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;
using xTagService.Providers.GraphQL;

namespace xTagService.Helpers
{
    public static class XTagServiceHelper
    {
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagEFRepository<TContext>,
            TContext
        > GetXTagEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagEFRepository<TContext>,
            TContext,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagEFRepository<TContext>,
                TContext,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagMongoRepository
        > GetXTagMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagMongoRepository,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagMongoRepository,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagInMemoryRepository
        > GetXTagInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagInMemoryRepository,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagInMemoryRepository,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseProvidedHasTag.cs

using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;

namespace xTagService.Interfaces
{
    public interface IXBaseProvidedHasTag<TEntity, TDto, TKey, THub> : IXBaseProvided<TEntity, TDto, TKey, THub>, IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseProvidedHasTagController.cs

using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;

namespace xTagService.Interfaces
{
    public interface IXBaseProvidedHasTagController<TEntity, TDto, TKey, THub> : IXBaseProvidedController<TEntity, TDto, TKey, THub>, IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseTagProvider.cs

using System.Threading;
using System.Threading.Tasks;
using xDataService.Interfaces;
using xDataService.Models;
using xTagService.Models.Dtos;

namespace xTagService.Interfaces
{
    public interface IXBaseTagProvider<TKey> : IXBaseReferencedProvider<XTagDto, TKey>
    {
        //
        #region Tools ...
        /// <summary>
        /// Add Reference a Tag to Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Reference a Tag to Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Tag for Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Tag for Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvided.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;

namespace xTagService.Interfaces
{
    /// <summary>
    /// a Tag Provided Service is a Model Provider Service which
    /// can Contains Tags ... 
    /// </summary>
    public interface IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach all Attached Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvidedController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Base;
using xPushService.Base;

namespace xTagService.Interfaces
{
    public interface IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces
{
    public interface IXTagProvider : IXBaseProvided<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProviderController.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces
{
    public interface IXTagProviderController : IXBaseProvidedController<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagDtoHub.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagDtoHub : IXBaseDtoHub<XTag, XTagDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagRepositoryService.cs

using xDataService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagRepositoryService : IXBaseRepositoryService<XTag, XTagDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagServiceProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagServiceProvider : IXBaseDtoProvider<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagEntityHub.cs

using xPushService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagEntityHub : IXBaseEntityHub<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagGraphQLTypeHelper.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagKeyGenerator.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagKeyGenerator : IXKeyGenerator<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepository.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepository : IXBaseRepository<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepositoryEvents.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepositoryEvents : IXBaseRepositoryEvents<XTag>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepositoryProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepositoryProvider : IXBaseEntityProvider<XTag, int, XTagEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagSeeder.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagSeeder : IXBaseDbSeeder<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Models\Dtos\XTagDto.cs

using xModels.Base;

namespace xTagService.Models.Dtos
{
    public class XTagDto : XBaseIntIDEntityDto
    {
        public string Tag { get; set; }
        public string References { get; set; } 
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Models\Entities\XTag.cs

using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xTagService.Models.Entities
{
    /// <summary>
    /// a Tag Model ...
    /// </summary>
    public class XTag : XBaseIntIDEntity
    {
        /// <summary>
        /// Tag Label ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string Tag { get; set; }

        /// <summary>
        /// Comma Separated List Which Provides Pointer to Specified 
        /// Model for Describe ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseProvidedHasTag.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;
using xIdentityModels.Extensions;
using System.Threading;
using xExceptions.Constants;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Dtos;

namespace xTagService.Providers
{
    public abstract class XBaseProvidedHasTag<TEntity, TDto, TKey, THub> : IXBaseProvidedHasTag<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly string[] permittedRoles;
        private readonly IXBaseTagProvider<TKey> tagProvider;
        private readonly IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider;

        protected XBaseProvidedHasTag(
            IXBaseTagProvider<TKey> tagProvider,
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            string[] permittedRoles = null
        )
        {
            this.provider = provider;
            this.tagProvider = tagProvider;
            this.permittedRoles = permittedRoles;
        }

        /// <summary>
        /// Check an Items is Owned for User or not ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public abstract bool IsOwned(
            TDto item,
            XUserClaimsInfoDto userInfo
        );
        public abstract bool IsOwned(
            TEntity item,
            XUserClaimsInfoDto userInfo
        );

        /// <summary>
        /// Check User Has Permission for Manipulate Data or not ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool HasPermision(
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !userInfo.IsNullOrDefault() &&
                userInfo.HasAccess(permittedRoles);

            //
            return result;
        }

        //
        #region Tag ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.AddReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Detach Tag fro Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Attach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await AttachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await DetachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach all Attached Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReferences(
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Get Specified Model's Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            isValid = await provider.IsExistsAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = (await tagProvider.GetAllReferences(
                providedForId: id,
                cancellationToken: cancellationToken
            ))
            .Select(x => x.Tag)
            .Distinct()
            .ToList();

            //
            return result;
        }
        #endregion

        //
        #region Provided ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Get(
            TKey id,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> GetAll(
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAllAsync(
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> FindOne(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindOneAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> FindMany(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindManyAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> Query(
            XQuery query,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Owned Items based on XQuery Pagination structure ...
        /// if supported ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userInfo"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> QueryOwned(
            XQuery query,
            XUserClaimsInfoDto userInfo = null,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            Expression<Func<TEntity, bool>> predicateor = null;
            if (!predicate.IsNull())
            {
                //
                var predicateFnc = predicate.Compile();
                predicateor = x =>
                    predicateFnc(x) &&
                    IsOwned(x, userInfo);
            }
            else
            {
                predicateor = x => IsOwned(x, userInfo);
            }

            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicateor,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Add an item values ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Add(
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.AddAsync(
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Update(
            TKey id,
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.UpdateAsync(
                id: id,
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Remove(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var item = await Get(
                id: id,
                cancellationToken: cancellationToken
            );
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.RemoveAsync(
                id: id,
                saveChanges: true,
                softDelete: false,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> Count(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.CountAsync(
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsExists(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseTagProvided.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;
using xIdentityModels.Extensions;
using xExceptions.Constants;
using System.Linq;

namespace xTagService.Providers
{
    public abstract class XBaseTagProvided<TEntity, TDto, TKey, THub> : IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly string[] permittedRoles;
        private readonly IXBaseTagProvider<TKey> tagProvider;
        private readonly IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider;

        protected XBaseTagProvided(
            IXBaseTagProvider<TKey> tagProvider,
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            string[] permittedRoles = null
        )
        {
            this.provider = provider;
            this.tagProvider = tagProvider;
            this.permittedRoles = permittedRoles;
        }

        /// <summary>
        /// Check an Items is Owned for User or not ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public abstract bool IsOwned(
            TDto item,
            XUserClaimsInfoDto userInfo
        );
        public abstract bool IsOwned(
            TEntity item,
            XUserClaimsInfoDto userInfo
        );

        /// <summary>
        /// Check User Has Permission for Manipulate Data or not ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool HasPermision(
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !userInfo.IsNullOrDefault() &&
                userInfo.HasAccess(permittedRoles);

            //
            return result;
        }

        //
        #region Actions ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.AddReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Detach Tag fro Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Attach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await AttachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await DetachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach all Attached Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReferences(
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Get Specified Model's Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            isValid = await provider.IsExistsAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = (await tagProvider.GetAllReferences(
                providedForId: id,
                cancellationToken: cancellationToken
            ))
            .Select(x => x.Tag)
            .Distinct()
            .ToList();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseTagProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xExceptions.Constants;
using xModels.Dtos;
using xTagService.Extensions;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;

namespace xTagService.Providers
{
    public abstract class XBaseTagProvider<TKey> : IXBaseTagProvider<TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        public string Provider { get; }

        /// <summary>
        /// Tag Provider for Maipulating Tags ...
        /// </summary>
        public IXTagServiceProvider TagProvider { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseTagProvider(
            string providedFor,
            IXTagServiceProvider tagProvider
        )
        {
            //
            Provider = providedFor;
            TagProvider = tagProvider;
        }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XTagDto> GetReference(
            TKey providedForId,
            int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            if (forIndex < 0)
            {
                forIndex = 0;
            }

            //
            // Retrieve Last Index ...
            var maxIndex = (await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            ))
            .Max();
            if (forIndex > maxIndex)
            {
                XException.NotFound.Throw();
            }

            //
            var indexedIdentifier = GetIndexedProvidedID(
                forIndex: forIndex,
                providedForId: providedForId
            );
            var result = await TagProvider.FindOneAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(indexedIdentifier)
            );
            if (result.IsNullOrDefault())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XTagDto>> GetAllReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns> 
        public async Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);

            //
            var result = (await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Select(x => x.References)
            .ToList()
            .SelectMany(x => x.ParseXReferenceList<TKey>())
            .Where(x => x.ProvidedFor == Provider && $"{x.ReferencedTo}" == $"{providedForId}")
            .OrderBy(x => x.Index)
            .AsEnumerable();

            //
            return result;
        }

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = (await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Count();

            //
            return result;
        }

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XTagDto>> QueryReferences(
            XQuery query,
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (query.IsNull() || providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await TagProvider.QueryAsync(
                query: query,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Id),
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XTagDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !model.IsNullOrDefault() &&
                !model.Tag.IsNullOrEmpty() &&
                model.Id.IsValidIntId() &&
                !providedForId.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Model Exists ...
            result = await TagProvider.IsExistsAsync(model.Id);
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Update Model by Retrieving ...
            model = await TagProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            // Retrieve all References ...
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check isReferenced or not ...
            result = references
                .Any(r =>
                    r.Id == model.Id &&
                    r.GetReferences()
                    .Any(rf =>
                        rf.ProvidedFor == Provider &&
                        rf.ReferencedTo == $"{providedForId}"));
            if (result)
            {
                return result;
            }

            //
            // Here means there is not any reference to ProvidedForId ...
            int forIndex = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            var modelReferences = model.GetReferences();
            modelReferences.Add(new XReference<string>
            {
                Index = forIndex,
                ProvidedFor = Provider,
                ReferencedTo = $"{providedForId}"
            });
            modelReferences = modelReferences
                .OrderBy(r => r.Index)
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update Data Base ...
            model = await TagProvider.UpdateAsync(
                id: model.Id,
                item: model,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XTagDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            // Since other Validations Handled in Calling, we Ignore them here ...
            var result =
                !model.IsNull() &&
                !reference.IsNullOrDefault() &&
                reference.ProvidedFor == Provider &&
                !reference.ReferencedTo.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await AddReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XTagDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !providedForId.IsNull() &&
                !model.IsNullOrDefault() &&
                model.Id.IsValidIntId();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Model ...
            model = await TagProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Reading Referencing Indexes ...
            var indexes = await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check Model Reference to ID ...
            var referencesCount = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            result = referencesCount == 0;
            if (result)
            {
                //
                // There is not any Reference to Remove ...
                return result;
            }

            //
            // Check Model is Trully Referenced to ProvidedForId or not ...
            var reference = model
                .GetReferences()
                .FirstOrDefault(r =>
                    r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}");
            result = !reference.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Remove Referenced Item from Model ...
            var modelReferences = model
                .GetReferences()
                .Where(r =>
                    !(r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}"))
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update DataBase ...
            model = await TagProvider.UpdateAsync(
                item: model,
                id: model.Id,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Get Max Exists Indexes ...
            var maxIndex = indexes.Max();

            //
            // Here We Have to Re Arrange Indexed ...
            if (reference.Index < maxIndex)
            {
                //
                var startIndex = reference.Index + 1;
                for (int i = startIndex; i <= maxIndex; i++)
                {
                    //
                    var dto = await GetReference(
                        forIndex: i,
                        providedForId: providedForId,
                        cancellationToken: cancellationToken
                    );
                    if (!dto.IsNullOrDefault())
                    {
                        //
                        var dtoReferences = dto.GetReferences();
                        dtoReferences
                        .ToList()
                        .ForEach(iref =>
                        {
                            //
                            if (
                                iref.Index == i &&
                                iref.ProvidedFor == Provider &&
                                iref.ReferencedTo == reference.ReferencedTo
                            )
                            {
                                iref.Index = i - 1;
                            }
                        });
                        dto = dto.UpdateReferences(dtoReferences);

                        //
                        dto = await TagProvider.UpdateAsync(
                            item: dto,
                            id: dto.Id,
                            saveChanges: true,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XTagDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (model.IsNullOrDefault() ||
                reference.IsNullOrDefault() ||
                reference.ReferencedTo.IsNull() ||
                reference.ProvidedFor != Provider)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = await RemoveReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = false;
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            if (!references.IsNull() && references.HasChild())
            {
                //
                foreach (var reference in references)
                {
                    //
                    // Remove Reference ...
                    var itemReferences = reference.GetReferences()
                        .Where(r =>
                            r.ProvidedFor != Provider ||
                            (r.ProvidedFor == Provider &&
                                r.ReferencedTo != $"{providedForId}"))
                        .ToList();
                    var updatedModel = reference.UpdateReferences(itemReferences);
                    updatedModel = await TagProvider.UpdateAsync(
                        saveChanges: true,
                        item: updatedModel,
                        id: updatedModel.Id,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                    if (!updatedModel.IsNullOrDefault())
                    {
                        result = true;
                    }
                }
            }

            //
            return result;
        }
        #endregion

        //
        #region Tools ...
        /// <summary>
        /// Add Reference a Tag to Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !tag.IsNullOrEmpty();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Tag Exists ...
            result = await IsExists(
                tag: tag,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                //
                // Create Tag if Not Exists ...
                var tagDto = new XTagDto
                {
                    Tag = tag,
                };
                tagDto = await TagProvider.AddAsync(
                    item: tagDto,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
                result = !tagDto.IsNullOrDefault();
                if (!result)
                {
                    XException.ActionFailed.Throw();
                }
            }

            //
            var dto = await GetTagByTag(
                tag: tag,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            result = await AddReference(
                model: dto,
                connectionId: connectionId,
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Tag to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result =
                !tag.IsNullOrEmpty() &&
                !reference.IsNullOrDefault() &&
                reference.ProvidedFor == Provider &&
                !reference.ReferencedTo.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await AddReference(
                tag: tag,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Tag for Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !tag.IsNullOrEmpty() &&
                !providedForId.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Tag Exists ...
            result = await IsExists(
                tag: tag,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            var dto = await GetTagByTag(
                tag: tag,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            result = await RemoveReference(
                model: dto,
                connectionId: connectionId,
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Tag for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !tag.IsNullOrEmpty() &&
                !reference.IsNullOrDefault() &&
                !reference.ReferencedTo.IsNull() &&
                reference.ProvidedFor == Provider;
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await RemoveReference(
                tag: tag,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        private string GetProvidedID(
            TKey providedForId,
            char splitter = '_'
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = $"{Provider}{splitter}{providedForId}";
            return result;
        }

        private string GetIndexedProvidedID(
            TKey providedForId,
            int forIndex,
            char splitter = '_'
        )
        {
            //
            var result = $"{GetProvidedID(providedForId, splitter)}{splitter}{forIndex}";

            //
            return result;
        }

        private async Task<IEnumerable<int>> GetReferencingIndexes(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = new List<int>();
            var referencings = await GetAllReferencings(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            isValid =
                !referencings.IsNull() &&
                referencings.HasChild();
            if (!isValid)
            {
                return result;
            }

            //
            result =
                referencings
                    .OrderBy(r => r.Index)
                    .Select(r => r.Index)
                    .ToList();

            //
            return result;
        }

        private async Task<XTagDto> GetTagByTag(
            string tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            XTagDto result = null;

            //
            if (!tag.IsNullOrEmpty())
            {
                //
                result = await TagProvider
                    .FindOneAsync(
                        predicate: x => x.Tag == tag,
                        cancellationToken: cancellationToken
                    );
            }

            //
            return result;
        }

        private async Task<bool> IsExists(
            string tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            if (!tag.IsNullOrEmpty())
            {
                //
                var dto = await GetTagByTag(
                    tag: tag,
                    cancellationToken: cancellationToken
                );
                result = !dto.IsNullOrDefault();
            }

            //
            return result;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XTagEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xTagService.Configurations.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers
{
    public class XTagEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XTagEntityRegisterar()
        : base(nameof(XTagEntityRegisterar))
        {
            //
            // Add XTag Entity ...
            AddEntity<XTag, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XTagEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XTagProvider.cs

using xCommons.Extensions;
using xIdentityModels.Models;
using xPushService.Providers;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Providers
{
    public class XTagProvider : XBaseProvided<XTag, XTagDto, int, XTagDtoHub>, IXTagProvider
    {
        public XTagProvider(
            IXTagServiceProvider provider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        { }

        public override bool IsOwned(
            XTagDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XTag item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagDtoHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagDtoHub : XBaseDtoHub<XTag, XTagDto, int>, IXTagDtoHub
    {
        public XTagDtoHub(
            ILogger<XTagDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xTagService.Interfaces.Dtos;
using xTagService.Interfaces.Entities;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagRepositoryService : XBaseRepositoryService<XTag, XTagDto, int>, IXTagRepositoryService
    {
        public XTagRepositoryService(
            IXTagRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagServiceProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagServiceProvider : XBaseDtoProvider<XTag, XTagDto, int, XTagDtoHub>, IXTagServiceProvider
    {
        public XTagServiceProvider(
            IHubContext<XTagDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXTagRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagEFRepository.cs

using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagEFRepository<TContext> : XBaseEFRepository<XTag, int, TContext>, IXTagRepository
    where TContext : XDbContext
    {
        public XTagEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagEntityHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagEntityHub : XBaseEntityHub<XTag, int>, IXTagEntityHub
    {
        public XTagEntityHub(
            ILogger<XTagEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagInMemoryRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagInMemoryRepository : XBaseInMemoryRepository<XTag, int>, IXTagRepository
    {
        public XTagInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagKeyGenerator.cs

using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagKeyGenerator : XIntKeyGenerator<XTag>, IXTagKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagMongoRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagMongoRepository : XBaseMongoRepository<XTag, int>, IXTagRepository
    {
        public XTagMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagRepositoryEvents.cs

using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagRepositoryEvents : XBaseRepositoryEvents<XTag>, IXTagRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagRepositoryProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagRepositoryProvider : XBaseEntityProvider<XTag, int, XTagEntityHub>, IXTagRepositoryProvider
    {
        public XTagRepositoryProvider(
            IHubContext<XTagEntityHub> hub,
            IXTagRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagSeederBase.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public abstract class XTagSeederBase : XBaseDbSeeder<XTag, int>, IXTagSeeder
    {
        protected XTagSeederBase(
            string entity,
            string database,
            IXTagRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphQLTypeHelper.cs

using xDataService.Configuration;
using xDataService.GraphQL;
using xTagService.Constants;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphQLTypeHelper : XBaseGraphQLTypeHelper<XTag, int>, IXTagGraphQLTypeHelper
    {
        public XTagGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XTagServiceConstants.XTagCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XTagServiceConstants.XTagSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphQuery.cs

using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphQuery : XBaseGraphQLQuery<XTag, int, XTagGraphType, IntGraphType>
    {
        public XTagGraphQuery(
            XDataServiceConfiguration configuration,
            IXTagRepository repository,
            IXTagGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphSchema.cs

using System;
using GraphQL.Types;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphSchema : Schema
    {
        public XTagGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XTagGraphQuery)services.GetService(typeof(XTagGraphQuery));
        }

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphType.cs

using xDataService.GraphQL;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphType : XBaseGraphObjectType<XTag, int>
    {
        public XTagGraphType() : base()
        {
            Field(x => x.Tag);
            Field(x => x.References);
        }
    }
}
