Files
xDataService/Providers/XBaseMongoRepository.cs
2026-05-15 02:51:02 +03:30

1158 lines
35 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;
namespace xDataService.Providers
{
/// <summary>
/// a Base Repository Pattern Implementation Specially for Mongo DBs using
/// EF Core Capabilities ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class XBaseMongoRepository<T, TKey> : IXBaseRepository<T, TKey>
where T : XBaseEntity<TKey>
{
//
#region Properties ...
private readonly string collectionName;
public List<WriteModel<T>> bulkCollection;
public readonly IMongoCollection<T> collection;
private readonly IXKeyGenerator<T, TKey> keyGenerator;
public readonly XDataBaseConfiguration dbConfiguration;
public readonly XDataServiceConfiguration configuration;
private readonly IXBaseRepositoryEvents<T> baseRepositoryEvents;
#endregion
//
#region Constructor ...
protected XBaseMongoRepository(
XDataBaseConfiguration dbConfiguration,
XDataServiceConfiguration configuration,
string collectionName = null,
IXKeyGenerator<T, TKey> keyGenerator = null,
IXBaseRepositoryEvents<T> baseRepositoryEvents = null
)
{
//
this.keyGenerator = keyGenerator;
this.configuration = configuration;
this.collectionName = collectionName
.IsNullOrEmpty() ?
typeof(T).Name :
collectionName;
this.dbConfiguration = dbConfiguration;
this.baseRepositoryEvents = baseRepositoryEvents;
//
var client = new MongoClient(dbConfiguration.GetMongoDbURI());
var database = client.GetDatabase(dbConfiguration.GetMongoDbDatabase());
//
bulkCollection = new List<WriteModel<T>>();
collection = database.GetCollection<T>(
this.collectionName
);
}
#endregion
//
#region Actions ...
//
#region Add ...
/// <summary>
/// add a new Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
// Add Action model to Bulk Collection ...
bulkCollection.Add(new InsertOneModel<T>(item));
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// add or update an Entity (add if not exists/update if exists) ...
/// </summary>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> AddOrUpdateAsync(
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isExists = await IsExistsAsync(
id: GetKey(item),
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
if (!isExists)
{
//
// Handle Key ...
item = await HandleKeyAsync(
item: item,
cancellationToken: cancellationToken
);
//
// Add Action model to Bulk Collection ...
bulkCollection
.Add(new InsertOneModel<T>(item));
}
else
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);
//
// Add Action model to Bulk Collection ...
bulkCollection
.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
if (isExists)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<T>(item));
}
else
{
//
baseRepositoryEvents
.AddEvent(new XBaseEventModel<T>(item));
}
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// add a range of new Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task AddRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return;
}
//
foreach (var item in items)
{
//
await AddAsync(
item: item,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
}
//
// Notify Event ...
if (
isValid &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.AddManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Update ...
/// <summary>
/// Update an Entity values ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> UpdateAsync(
TKey id,
T item,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, id);
//
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = false });
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.UpdateEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// Update a range of Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> UpdateRangeAsync(
IEnumerable<T> items,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = false;
var isValid = !items.IsNull() && items.HasChild();
if (!isValid)
{
return result;
}
//
foreach (var item in items)
{
//
var updated = await UpdateAsync(
item: item,
id: item.Id,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
if (!updated.IsNullOrDefault() && !result)
{
result = true;
}
}
//
return result;
}
#endregion
//
#region Remove ...
/// <summary>
/// remove an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
TKey id,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// Retrieve Item ...
var item = await GetAsync(
id: id,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
if (item.IsNull())
{
return null;
}
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, id);
//
// Check SoftDelete ...
if (softDelete && configuration.EnableSoftDelete)
{
//
// Set Soft Delete ...
item.Deleted = true;
//
// Update ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
else
{
//
// Delete ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new DeleteOneModel<T>(filter));
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveEvent(new XBaseEventModel<T>(item));
}
//
// Return result base on action Succeed ...
return isSucceed ?
item :
null;
}
/// <summary>
/// remove an Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> RemoveAsync(
T item,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
var result = await RemoveAsync(
id: item.Id,
softDelete: softDelete,
saveChanges: saveChanges,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// remove a range of exists Entities ...
/// </summary>
/// <param name="items"></param>
/// <param name="softDelete"></param>
/// <param name="saveChanges"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RemoveRangeAsync(
IEnumerable<T> items,
bool softDelete = true,
bool saveChanges = true,
CancellationToken cancellationToken = default
)
{
//
// loop through items ...
foreach (var item in items)
{
//
// Filter ...
var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);
//
// Check Soft Delete ...
if (softDelete && configuration.EnableSoftDelete)
{
//
// Set Soft Delete ...
item.Deleted = true;
//
// Update ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
}
else
{
//
// Delete ...
// Add Action model to Bulk Collection ...
bulkCollection.Add(new DeleteOneModel<T>(filter));
}
}
//
// Check action is Succeeded or not ...
var isSucceed = false;
if (saveChanges)
{
//
// Get Modified Count ...
var qResult = await SaveChangesAsync(cancellationToken);
//
// set isSucceed Value based on Changes ...
isSucceed = qResult > 0;
}
//
// Notify Event ...
if (
isSucceed &&
!baseRepositoryEvents.IsNull()
)
{
//
baseRepositoryEvents
.RemoveManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
}
}
#endregion
//
#region Count ...
/// <summary>
/// count all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountAsync(
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.CountAsync(cancellationToken);
//
return result;
}
/// <summary>
/// count all exists Entities Pages by providing page size ...
/// </summary>
/// <param name="pageSize"></param>
/// <param name="totalItems"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> PagesCountAsync(
int pageSize,
int? totalItems = null,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
int pagesCount = count / pageSize;
//
if (count % pageSize > 0)
{
pagesCount++;
}
//
return pagesCount;
}
#endregion
//
#region Retrieve ...
/// <summary>
/// retrieve whole items as queryable ...
/// </summary>
/// <param name="asNoTracking">a flag for Tracking behaviour</param>
/// <param name="predicate">an Expression for Filter Items ...</param>
/// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
/// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
/// <returns></returns>
public IQueryable<T> AsQueryable(
bool asNoTracking = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
var result = collection
.AsQueryable();
//
// Apply Predicate ...
if (!predicate.IsNull())
{
result = result
.Where(predicate);
}
//
// Apply Includes ...
if (!includeBuilder.IsNull())
{
//
// Since Mongo Queryable doesnt Support Includes ...
// we ignore this ...
result = (IMongoQueryable<T>)includeBuilder(result);
}
//
// Apply Ordering ...
if (!orderBuilder.IsNull())
{
result = (IMongoQueryable<T>)orderBuilder(result);
}
//
return result;
}
/// <summary>
/// retrieve an Entity by it's Id ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> GetAsync(
TKey id,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(x => GetKey(x).ToString() == id.ToString())
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> GetAllAsync(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve all exists Entities
/// as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <returns></returns>
public IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.AsAsyncEnumerable();
//
return result;
}
/// <summary>
/// find an Entity by providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> FindOneAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
predicate: predicator,
includeBuilder: includeBuilder
)
.Where(predicate)
.FirstOrDefaultAsync(cancellationToken);
//
return result;
}
/// <summary>
/// find a collection of Entities by proving a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<T>> FindManyAsync(
Expression<Func<T, bool>> predicate,
bool ignoreSoftDeleteds = true,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
predicate: predicator,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
)
.Where(predicate)
.ToListAsync(cancellationToken);
//
return result;
}
/// <summary>
/// retrieve Entities based on XQuery Pagination structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<T>> QueryAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
Expression<Func<T, bool>> predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Normalize Query ...
query = query.NormalizeQuery(configuration);
//
var items = await GetAllAsync();
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Prepare Result ...
var result = new XQueryResult<T>
{
Page = query.Page,
Items = items.ToList(),
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
//
#region Exists ...
/// <summary>
/// Check an Entity exists or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> IsExistsAsync(
TKey id,
bool ignoreSoftDeleteds = true,
CancellationToken cancellationToken = default
)
{
//
// Prepare Ignore Soft Deleted Predicator ...
Expression<Func<T, bool>> predicator = null;
if (ignoreSoftDeleteds)
{
predicator = x => !x.Deleted;
}
var result = await AsQueryable(
asNoTracking: true,
orderBuilder: null,
includeBuilder: null,
predicate: predicator
)
.AnyAsync(
cancellationToken: cancellationToken,
predicate: x => GetKey(x).ToString() == id.ToString());
//
return result;
}
#endregion
//
#region Unit Of Work ...
/// <summary>
/// Save all unsaved Transactions on DbContext ...
/// used fo Unit Of Works Design Pattern ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Write all Bulk Models which stored inside bulkCollection ...
var result = await collection
.BulkWriteAsync(
options: null,
requests: bulkCollection,
cancellationToken: cancellationToken
);
//
// Clear Bulk Collection ...
bulkCollection.Clear();
//
// Return number of Modified Documents ...
var resultCount = (int)result.ModifiedCount +
(int)result.InsertedCount +
(int)result.DeletedCount;
//
return resultCount;
}
catch (Exception ex)
{
//
// Log Thrown Exception ...
Console.WriteLine($"XMongo Repository Exception: {ex.Message} ...");
//
// Return less than zero value ...
return -1;
}
}
#endregion
//
#region Key ...
/// <summary>
/// Retrieve Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public TKey GetKey(T item)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
//
var keyString = string.Empty;
if (keyProp.IsNull())
{
keyString = string.Empty;
}
else
{
keyString = keyProp.GetValue(item).ToString();
}
//
if (keyString.IsNullOrEmpty())
{
return default(TKey);
}
//
// Prevent Deserializing issues throug JsonReader ...
if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
{
return item.Id;
}
//
return keyString.FromJSON<TKey>();
}
/// <summary>
/// Set Key of Entity ...
/// </summary>
/// <param name="item"></param>
/// <param name="id"></param>
public void SetKey(
ref T item,
TKey id
)
{
//
var props = item.GetType().GetProperties();
var keyProp = props.FirstOrDefault(p => p.Name == "Id");
if (keyProp.IsNull())
{
return;
}
//
Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
keyProp.SetValue(item, safeValue, null);
}
/// <summary>
/// Handle Checking Key ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<T> HandleKeyAsync(
T item,
CancellationToken cancellationToken = default
)
{
//
var keyType = typeof(TKey);
//
// Handle Guid Key Type ...
// Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
if (
(
keyType == typeof(Guid) ||
keyType == typeof(string)
) &&
keyGenerator.IsEmpty(item.Id)
)
{
//
var newKey = await keyGenerator.GenerateKey(this);
//
SetKey(ref item, newKey);
}
//
return item;
}
#endregion
//
#region Detach ...
/// <summary>
/// Detach an Entity ...
/// </summary>
/// <param name="item"></param>
public void Detach(T item) { }
/// <summary>
/// Detach an Enumerable of Entities ...
/// </summary>
/// <param name="items"></param>
public void Detach(IEnumerable<T> items) { }
/// <summary>
/// Detach a Query Result of Entity ...
/// </summary>
/// <param name="query"></param>
public void Detach(XQueryResult<T> query) { }
#endregion
#endregion
//
#region Others ...
public void Dispose() { }
public string GetPropValues(T item)
{
//
var props = item.GetType().GetProperties();
var vals = props.Select(p => p.GetValue(p.Name));
//
return vals.ToJSON();
}
#endregion
//
#region Private ...
#endregion
}
}