|
|
|
@ -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); |
|
|
|
} |
|
|
|
} |
|
|
|
} |