last ...
This commit is contained in:
@@ -0,0 +1,149 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using xCategoryService.Models.Dtos;
|
||||||
|
using xCategoryService.Models.Entities;
|
||||||
|
using xCommons.Extensions;
|
||||||
|
using xDataService.Extensions;
|
||||||
|
using xDataService.Models;
|
||||||
|
|
||||||
|
namespace xCategoryService.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 XCategory 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 XCategoryDto 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 XCategory UpdateReferences(
|
||||||
|
this XCategory source,
|
||||||
|
IList<XReference<string>> references,
|
||||||
|
bool forceClean = true
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
XCategory 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 XCategoryDto UpdateReferences(
|
||||||
|
this XCategoryDto source,
|
||||||
|
IList<XReference<string>> references,
|
||||||
|
bool forceClean = true
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
XCategoryDto result = source;
|
||||||
|
|
||||||
|
//
|
||||||
|
if (!source.IsNullOrDefault())
|
||||||
|
{
|
||||||
|
//
|
||||||
|
result = source;
|
||||||
|
|
||||||
|
//
|
||||||
|
if (forceClean)
|
||||||
|
{
|
||||||
|
result.References = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if (!references.IsNull() &&
|
||||||
|
references.HasChild())
|
||||||
|
{
|
||||||
|
result.References = references.ToXReferenceString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using xCategoryService.Models.Dtos;
|
||||||
|
using xDataService.Interfaces;
|
||||||
|
|
||||||
|
namespace xCategoryService.Interfaces
|
||||||
|
{
|
||||||
|
public interface IXBaseCategoryProvider<TKey> : IXBaseReferencedProvider<XCategoryDto, TKey>
|
||||||
|
{}
|
||||||
|
}
|
||||||
@@ -0,0 +1,710 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using xCategoryService.Extensions;
|
||||||
|
using xCategoryService.Interfaces;
|
||||||
|
using xCategoryService.Interfaces.Dtos;
|
||||||
|
using xCategoryService.Models.Dtos;
|
||||||
|
using xCommons.Extensions;
|
||||||
|
using xDataService.Extensions;
|
||||||
|
using xDataService.Models;
|
||||||
|
using xExceptions.Constants;
|
||||||
|
using xModels.Dtos;
|
||||||
|
|
||||||
|
namespace xCategoryService.Providers
|
||||||
|
{
|
||||||
|
public abstract class XBaseCategoryProvider<TKey> : IXBaseCategoryProvider<TKey>
|
||||||
|
{
|
||||||
|
//
|
||||||
|
#region Props ...
|
||||||
|
/// <summary>
|
||||||
|
/// Provider Identifier ...
|
||||||
|
/// </summary>
|
||||||
|
public string Provider { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tag Provider for Maipulating Tags ...
|
||||||
|
/// </summary>
|
||||||
|
public IXCategoryServiceProvider CategoryProvider { get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//
|
||||||
|
#region Constructor ...
|
||||||
|
public XBaseCategoryProvider(
|
||||||
|
string providedFor,
|
||||||
|
IXCategoryServiceProvider categoryProvider
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Provider = providedFor;
|
||||||
|
CategoryProvider = categoryProvider;
|
||||||
|
}
|
||||||
|
#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<XCategoryDto> 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 CategoryProvider.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<XCategoryDto>> GetAllReferences(
|
||||||
|
TKey providedForId,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Validate ...
|
||||||
|
if (providedForId.IsNull())
|
||||||
|
{
|
||||||
|
XException.InvalidArgs.Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
var identifier = GetProvidedID(providedForId);
|
||||||
|
var result = await CategoryProvider.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 CategoryProvider.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 CategoryProvider.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="query"></param>
|
||||||
|
/// <param name="providedForId"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<XQueryResult<XCategoryDto>> QueryReferences(
|
||||||
|
XQuery query,
|
||||||
|
TKey providedForId,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Validate ...
|
||||||
|
if (query.IsNull() || providedForId.IsNull())
|
||||||
|
{
|
||||||
|
XException.InvalidArgs.Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
var identifier = GetProvidedID(providedForId);
|
||||||
|
var result = await CategoryProvider.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(
|
||||||
|
XCategoryDto model,
|
||||||
|
TKey providedForId,
|
||||||
|
string connectionId = null,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
var result = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate ...
|
||||||
|
result = !model.IsNullOrDefault() &&
|
||||||
|
model.Id.IsValidIntId() &&
|
||||||
|
!providedForId.IsNull();
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
XException.InvalidArgs.Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check Model Exists ...
|
||||||
|
result = await CategoryProvider.IsExistsAsync(model.Id);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
XException.NotFound.Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update Model by Retrieving ...
|
||||||
|
model = await CategoryProvider.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 CategoryProvider.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(
|
||||||
|
XCategoryDto 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(
|
||||||
|
XCategoryDto 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 CategoryProvider.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 CategoryProvider.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 CategoryProvider.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(
|
||||||
|
XCategoryDto 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 CategoryProvider.UpdateAsync(
|
||||||
|
saveChanges: true,
|
||||||
|
item: updatedModel,
|
||||||
|
id: updatedModel.Id,
|
||||||
|
connectionId: connectionId,
|
||||||
|
cancellationToken: cancellationToken
|
||||||
|
);
|
||||||
|
if (!updatedModel.IsNullOrDefault())
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user