This commit is contained in:
2026-05-28 07:32:56 +03:30
parent c977339613
commit db8b50d02d
7 changed files with 1319 additions and 3 deletions
+723
View File
@@ -0,0 +1,723 @@
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
}
}
+384
View File
@@ -0,0 +1,384 @@
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
}
}
@@ -4,7 +4,7 @@ using xDataService.Providers;
using xTagService.Interfaces;
using xTagService.Models.Entities;
namespace xTagService.Providers.Entities
namespace xTagService.Providers
{
public abstract class XTagSeederBase : XBaseDbSeeder<XTag, int>, IXTagSeeder
{