Implemented data filters for mongodb. Revised IGeneratesDomainEvents

pull/272/head
Halil İbrahim Kalkan 8 years ago
parent f9caa9d365
commit b136f483fc

@ -1,26 +1,34 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations.Schema;
namespace Volo.Abp.Domain.Entities namespace Volo.Abp.Domain.Entities
{ {
[Serializable] [Serializable]
public abstract class AggregateRoot : Entity, IAggregateRoot public abstract class AggregateRoot : Entity, IAggregateRoot
{ {
[NotMapped] //TODO: Better to handle in EF Core layer, or just use get/set methods instead of a property? private readonly ICollection<object> _domainEvents = new Collection<object>();
public virtual ICollection<object> DomainEvents => _domainEvents ?? (_domainEvents = new Collection<object>());
private ICollection<object> _domainEvents; protected virtual void AddDomainEvent(object eventData)
{
_domainEvents.Add(eventData);
}
public virtual IEnumerable<object> GetDomainEvents()
{
return _domainEvents;
}
public virtual void ClearDomainEvents()
{
_domainEvents.Clear();
}
} }
[Serializable] [Serializable]
public abstract class AggregateRoot<TKey> : Entity<TKey>, IAggregateRoot<TKey> public abstract class AggregateRoot<TKey> : Entity<TKey>, IAggregateRoot<TKey>
{ {
[NotMapped] //TODO: Better to handle in EF Core layer, or just use get/set methods instead of a property?? private readonly ICollection<object> _domainEvents = new Collection<object>();
public virtual ICollection<object> DomainEvents => _domainEvents ?? (_domainEvents = new Collection<object>());
private ICollection<object> _domainEvents;
protected AggregateRoot() protected AggregateRoot()
{ {
@ -32,5 +40,20 @@ namespace Volo.Abp.Domain.Entities
{ {
} }
protected virtual void AddDomainEvent(object eventData)
{
_domainEvents.Add(eventData);
}
public virtual IEnumerable<object> GetDomainEvents()
{
return _domainEvents;
}
public virtual void ClearDomainEvents()
{
_domainEvents.Clear();
}
} }
} }

@ -76,7 +76,7 @@ namespace Volo.Abp.Domain.Entities
{ {
var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaParam = Expression.Parameter(typeof(TEntity));
var lambdaBody = Expression.Equal( var lambdaBody = Expression.Equal(
Expression.PropertyOrField(lambdaParam, "Id"), Expression.PropertyOrField(lambdaParam, nameof(Entity<TKey>.Id)),
Expression.Constant(id, typeof(TKey)) Expression.Constant(id, typeof(TKey))
); );

@ -2,8 +2,12 @@
namespace Volo.Abp.Domain.Entities namespace Volo.Abp.Domain.Entities
{ {
//TODO: Re-consider this interface
public interface IGeneratesDomainEvents public interface IGeneratesDomainEvents
{ {
ICollection<object> DomainEvents { get; } IEnumerable<object> GetDomainEvents();
void ClearDomainEvents();
} }
} }

@ -50,17 +50,18 @@ namespace Volo.Abp.Domain.Repositories
return Task.CompletedTask; return Task.CompletedTask;
} }
protected virtual IQueryable<TEntity> ApplyDataFilters(IQueryable<TEntity> query) protected virtual TQueryable ApplyDataFilters<TQueryable>(TQueryable query)
where TQueryable : IQueryable<TEntity>
{ {
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{ {
query = query.WhereIf(DataFilter.IsEnabled<ISoftDelete>(), e => ((ISoftDelete)e).IsDeleted == false); query = (TQueryable)query.WhereIf(DataFilter.IsEnabled<ISoftDelete>(), e => ((ISoftDelete)e).IsDeleted == false);
} }
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))
{ {
var tenantId = CurrentTenant.Id; var tenantId = CurrentTenant.Id;
query = query.WhereIf(DataFilter.IsEnabled<IMultiTenant>(), e => ((IMultiTenant)e).TenantId == tenantId); query = (TQueryable)query.WhereIf(DataFilter.IsEnabled<IMultiTenant>(), e => ((IMultiTenant)e).TenantId == tenantId);
} }
return query; return query;

@ -189,13 +189,14 @@ namespace Volo.Abp.EntityFrameworkCore
return; return;
} }
if (generatesDomainEventsEntity.DomainEvents.IsNullOrEmpty()) var entityEvents = generatesDomainEventsEntity.GetDomainEvents().ToArray();
if (entityEvents.IsNullOrEmpty())
{ {
return; return;
} }
domainEvents.AddRange(generatesDomainEventsEntity.DomainEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData))); domainEvents.AddRange(entityEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData)));
generatesDomainEventsEntity.DomainEvents.Clear(); generatesDomainEventsEntity.ClearDomainEvents();
} }
protected virtual void HandleConcurrencyStamp(EntityEntry entry) protected virtual void HandleConcurrencyStamp(EntityEntry entry)

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading; using System.Threading;
@ -6,6 +7,7 @@ using System.Threading.Tasks;
using MongoDB.Driver; using MongoDB.Driver;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Domain.Repositories.MongoDB namespace Volo.Abp.Domain.Repositories.MongoDB
{ {
@ -74,7 +76,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
protected override IQueryable<TEntity> GetQueryable() protected override IQueryable<TEntity> GetQueryable()
{ {
return Collection.AsQueryable(); return ApplyDataFilters(Collection.AsQueryable());
} }
protected virtual FilterDefinition<TEntity> CreateEntityFilter(TEntity entity) protected virtual FilterDefinition<TEntity> CreateEntityFilter(TEntity entity)
@ -117,24 +119,24 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
return entity; return entity;
} }
public virtual void Delete(TKey id, bool autoSave = false) public virtual async Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
Collection.DeleteOne(CreateEntityFilter(id)); return await Collection.Find(CreateEntityFilter(id, true)).FirstOrDefaultAsync(cancellationToken);
} }
public virtual Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default) public virtual TEntity Find(TKey id)
{ {
return Collection.DeleteOneAsync(CreateEntityFilter(id), cancellationToken); return Collection.Find(CreateEntityFilter(id, true)).FirstOrDefault();
} }
public virtual async Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default) public virtual void Delete(TKey id, bool autoSave = false)
{ {
return await Collection.Find(CreateEntityFilter(id)).FirstOrDefaultAsync(cancellationToken); Collection.DeleteOne(CreateEntityFilter(id));
} }
public virtual TEntity Find(TKey id) public virtual Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{ {
return Collection.Find(CreateEntityFilter(id)).FirstOrDefault(); return Collection.DeleteOneAsync(CreateEntityFilter(id), cancellationToken);
} }
protected override FilterDefinition<TEntity> CreateEntityFilter(TEntity entity) protected override FilterDefinition<TEntity> CreateEntityFilter(TEntity entity)
@ -142,9 +144,33 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
return Builders<TEntity>.Filter.Eq(e => e.Id, entity.Id); return Builders<TEntity>.Filter.Eq(e => e.Id, entity.Id);
} }
protected virtual FilterDefinition<TEntity> CreateEntityFilter(TKey id) protected virtual FilterDefinition<TEntity> CreateEntityFilter(TKey id, bool applyFilters = false)
{ {
return Builders<TEntity>.Filter.Eq(e => e.Id, id); var filters = new List<FilterDefinition<TEntity>>
{
Builders<TEntity>.Filter.Eq(e => e.Id, id)
};
if (applyFilters)
{
AddGlobalFilters(filters);
}
return Builders<TEntity>.Filter.And(filters);
}
protected virtual void AddGlobalFilters(List<FilterDefinition<TEntity>> filters)
{
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)) && DataFilter.IsEnabled<ISoftDelete>())
{
filters.Add(Builders<TEntity>.Filter.Eq(e => ((ISoftDelete) e).IsDeleted, false));
}
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))
{
var tenantId = CurrentTenant.Id;
filters.Add(Builders<TEntity>.Filter.Eq(e => ((IMultiTenant) e).TenantId, tenantId));
}
} }
} }
} }

@ -0,0 +1,9 @@
using Volo.Abp.TestApp.Testing;
namespace Volo.Abp.MongoDB
{
public class MultiTenant_Filter_Tests : MultiTenant_Filter_Tests<AbpMongoDbTestModule>
{
}
}

@ -9,7 +9,7 @@ using Xunit;
namespace Volo.Abp.MongoDB namespace Volo.Abp.MongoDB
{ {
public class MongoDb_Repository_Basic_Tests : Repository_Basic_Tests<AbpMongoDbTestModule> public class Repository_Basic_Tests : Repository_Basic_Tests<AbpMongoDbTestModule>
{ {
[Fact] [Fact]
public async Task GetAsync() public async Task GetAsync()

@ -0,0 +1,9 @@
using Volo.Abp.TestApp.Testing;
namespace Volo.Abp.MongoDB
{
public class Repository_Queryable_Tests : Repository_Queryable_Tests<AbpMongoDbTestModule>
{
}
}

@ -0,0 +1,9 @@
using Volo.Abp.TestApp.Testing;
namespace Volo.Abp.MongoDB
{
public class SoftDelete_Filter_Tests : SoftDelete_Filter_Tests<AbpMongoDbTestModule>
{
}
}

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -41,7 +42,7 @@ namespace Volo.Abp.TestApp.Domain
var oldName = Name; var oldName = Name;
Name = name; Name = name;
DomainEvents.Add(new PersonNameChangedEvent{Person = this, OldName = oldName}); AddDomainEvent(new PersonNameChangedEvent{Person = this, OldName = oldName});
} }
} }
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
@ -22,7 +23,27 @@ namespace Volo.Abp.TestApp.Testing
} }
[Fact] [Fact]
public void Should_Not_Get_Deleted_Entities_By_Default() public void Should_Not_Get_Deleted_Entities_Linq()
{
WithUnitOfWork(() =>
{
var person = PersonRepository.FirstOrDefault(p => p.Name == "John-Deleted");
person.ShouldBeNull();
});
}
[Fact]
public async Task Should_Not_Get_Deleted_Entities_By_Id()
{
await WithUnitOfWorkAsync(async () =>
{
var person = await PersonRepository.FindAsync(TestDataBuilder.UserJohnDeletedId);
person.ShouldBeNull();
});
}
[Fact]
public void Should_Not_Get_Deleted_Entities_By_Default_ToList()
{ {
WithUnitOfWork(() => WithUnitOfWork(() =>
{ {

Loading…
Cancel
Save