|
|
|
@ -4,7 +4,12 @@ using System.Linq;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Volo.Abp.Auditing;
|
|
|
|
|
using Volo.Abp.Domain.Entities;
|
|
|
|
|
using Volo.Abp.Domain.Entities.Events;
|
|
|
|
|
using Volo.Abp.EventBus.Distributed;
|
|
|
|
|
using Volo.Abp.EventBus.Local;
|
|
|
|
|
using Volo.Abp.Guids;
|
|
|
|
|
using Volo.Abp.MemoryDb;
|
|
|
|
|
|
|
|
|
|
namespace Volo.Abp.Domain.Repositories.MemoryDb
|
|
|
|
@ -20,62 +25,224 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
|
|
|
|
|
public virtual IMemoryDatabase Database => DatabaseProvider.GetDatabase();
|
|
|
|
|
|
|
|
|
|
protected IMemoryDatabaseProvider<TMemoryDbContext> DatabaseProvider { get; }
|
|
|
|
|
|
|
|
|
|
public ILocalEventBus LocalEventBus { get; set; }
|
|
|
|
|
|
|
|
|
|
public IDistributedEventBus DistributedEventBus { get; set; }
|
|
|
|
|
|
|
|
|
|
public IEntityChangeEventHelper EntityChangeEventHelper { get; set; }
|
|
|
|
|
|
|
|
|
|
public IAuditPropertySetter AuditPropertySetter { get; set; }
|
|
|
|
|
|
|
|
|
|
public IGuidGenerator GuidGenerator { get; set; }
|
|
|
|
|
|
|
|
|
|
public MemoryDbRepository(IMemoryDatabaseProvider<TMemoryDbContext> databaseProvider)
|
|
|
|
|
{
|
|
|
|
|
DatabaseProvider = databaseProvider;
|
|
|
|
|
|
|
|
|
|
LocalEventBus = NullLocalEventBus.Instance;
|
|
|
|
|
DistributedEventBus = NullDistributedEventBus.Instance;
|
|
|
|
|
EntityChangeEventHelper = NullEntityChangeEventHelper.Instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override IQueryable<TEntity> GetQueryable()
|
|
|
|
|
{
|
|
|
|
|
return ApplyDataFilters(Collection.AsQueryable());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task TriggerDomainEventsAsync(object entity)
|
|
|
|
|
{
|
|
|
|
|
var generatesDomainEventsEntity = entity as IGeneratesDomainEvents;
|
|
|
|
|
if (generatesDomainEventsEntity == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var localEvents = generatesDomainEventsEntity.GetLocalEvents()?.ToArray();
|
|
|
|
|
if (localEvents != null && localEvents.Any())
|
|
|
|
|
{
|
|
|
|
|
foreach (var localEvent in localEvents)
|
|
|
|
|
{
|
|
|
|
|
await LocalEventBus.PublishAsync(localEvent.GetType(), localEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generatesDomainEventsEntity.ClearLocalEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var distributedEvents = generatesDomainEventsEntity.GetDistributedEvents()?.ToArray();
|
|
|
|
|
if (distributedEvents != null && distributedEvents.Any())
|
|
|
|
|
{
|
|
|
|
|
foreach (var distributedEvent in distributedEvents)
|
|
|
|
|
{
|
|
|
|
|
await DistributedEventBus.PublishAsync(distributedEvent.GetType(), distributedEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generatesDomainEventsEntity.ClearDistributedEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual bool IsHardDeleted(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
if (!(UnitOfWorkManager?.Current?.Items.GetOrDefault(UnitOfWorkItemNames.HardDeletedEntities) is HashSet<IEntity> hardDeletedEntities))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hardDeletedEntities.Contains(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void CheckAndSetId(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
if (entity is IEntity<Guid> entityWithGuidId)
|
|
|
|
|
{
|
|
|
|
|
TrySetGuidId(entityWithGuidId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void TrySetGuidId(IEntity<Guid> entity)
|
|
|
|
|
{
|
|
|
|
|
if (entity.Id != default)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EntityHelper.TrySetId(
|
|
|
|
|
entity,
|
|
|
|
|
() => GuidGenerator.Create(),
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void SetCreationAuditProperties(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
AuditPropertySetter.SetCreationProperties(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void SetModificationAuditProperties(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
AuditPropertySetter.SetModificationProperties(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void SetDeletionAuditProperties(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
AuditPropertySetter.SetDeletionProperties(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task TriggerEntityCreateEvents(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityCreatedEventOnUowCompletedAsync(entity);
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityCreatingEventAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task TriggerEntityUpdateEventsAsync(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityUpdatedEventOnUowCompletedAsync(entity);
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityUpdatingEventAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task TriggerEntityDeleteEventsAsync(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityDeletedEventOnUowCompletedAsync(entity);
|
|
|
|
|
await EntityChangeEventHelper.TriggerEntityDeletingEventAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task ApplyAbpConceptsForAddedEntityAsync(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
CheckAndSetId(entity);
|
|
|
|
|
SetCreationAuditProperties(entity);
|
|
|
|
|
await TriggerEntityCreateEvents(entity);
|
|
|
|
|
await TriggerDomainEventsAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task ApplyAbpConceptsForDeletedEntityAsync(TEntity entity)
|
|
|
|
|
{
|
|
|
|
|
SetDeletionAuditProperties(entity);
|
|
|
|
|
await TriggerEntityDeleteEventsAsync(entity);
|
|
|
|
|
await TriggerDomainEventsAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task<TEntity> FindAsync(
|
|
|
|
|
Expression<Func<TEntity, bool>> predicate,
|
|
|
|
|
bool includeDetails = true,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return Task.FromResult(Collection.AsQueryable().Where(predicate).SingleOrDefault());
|
|
|
|
|
return Task.FromResult(GetQueryable().Where(predicate).SingleOrDefault());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
|
|
|
|
|
public override async Task DeleteAsync(
|
|
|
|
|
Expression<Func<TEntity, bool>> predicate,
|
|
|
|
|
bool autoSave = false,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
var entities = Collection.AsQueryable().Where(predicate).ToList();
|
|
|
|
|
var entities = GetQueryable().Where(predicate).ToList();
|
|
|
|
|
foreach (var entity in entities)
|
|
|
|
|
{
|
|
|
|
|
Collection.Remove(entity);
|
|
|
|
|
await DeleteAsync(entity, autoSave, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
|
|
|
|
public override async Task<TEntity> InsertAsync(
|
|
|
|
|
TEntity entity,
|
|
|
|
|
bool autoSave = false,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
await ApplyAbpConceptsForAddedEntityAsync(entity);
|
|
|
|
|
|
|
|
|
|
Collection.Add(entity);
|
|
|
|
|
return Task.FromResult(entity);
|
|
|
|
|
|
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
|
|
|
|
|
|
|
|
|
public override async Task<TEntity> UpdateAsync(
|
|
|
|
|
TEntity entity,
|
|
|
|
|
bool autoSave = false,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
SetModificationAuditProperties(entity);
|
|
|
|
|
|
|
|
|
|
if (entity is ISoftDelete softDeleteEntity && softDeleteEntity.IsDeleted)
|
|
|
|
|
{
|
|
|
|
|
SetDeletionAuditProperties(entity);
|
|
|
|
|
await TriggerEntityDeleteEventsAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await TriggerEntityUpdateEventsAsync(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TriggerDomainEventsAsync(entity);
|
|
|
|
|
|
|
|
|
|
Collection.Update(entity);
|
|
|
|
|
return Task.FromResult(entity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task DeleteAsync(
|
|
|
|
|
TEntity entity,
|
|
|
|
|
bool autoSave = false,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
Collection.Remove(entity);
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
await ApplyAbpConceptsForDeletedEntityAsync(entity);
|
|
|
|
|
|
|
|
|
|
if (entity is ISoftDelete softDeleteEntity && !IsHardDeleted(entity))
|
|
|
|
|
{
|
|
|
|
|
softDeleteEntity.IsDeleted = true;
|
|
|
|
|
Collection.Update(entity);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Collection.Remove(entity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return Task.FromResult(Collection.ToList());
|
|
|
|
|
return Task.FromResult(GetQueryable().ToList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Task<long> GetCountAsync(CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return Task.FromResult(Collection.LongCount());
|
|
|
|
|
return Task.FromResult(GetQueryable().LongCount());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -126,13 +293,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
|
|
|
|
|
|
|
|
|
|
public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
var entity = await FindAsync(id, cancellationToken: cancellationToken);
|
|
|
|
|
if (entity == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await DeleteAsync(entity, autoSave, cancellationToken);
|
|
|
|
|
await DeleteAsync(x => x.Id.Equals(id), autoSave, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|