Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into dev

pull/7114/head
Halil İbrahim Kalkan 6 years ago
parent
commit
25afb25dc4
  1. 6
      docs/en/Community-Articles/2020-12-11-Using-Angular-Material-Components-With-ABP-Framework/POST.md
  2. 215
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs
  3. 67
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs
  4. 58
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HardDelete_Tests.cs
  5. 13
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs
  6. 10
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs
  7. 11
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagementProvider.cs

6
docs/en/Community-Articles/2020-12-11-Using-Angular-Material-Components-With-ABP-Framework/POST.md

@ -260,7 +260,7 @@ import { MatFormFieldModule } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MatSelectModule } from "@angular/material/select";
import { MatIconModule } from "@angular/material/icon";
import { MatNativeDateModule } from '@angular/material/core';
import { MatNativeDateModule } from "@angular/material/core";
@NgModule({
imports: [
@ -1576,6 +1576,10 @@ Final UI looks as shown below:
![Author With Books](./author-with-books.gif)
## The Source Code
You can download the source code from [here](https://github.com/abpframework/abp-samples/tree/master/AcmeBookStoreAngularMaterial).
## Conclusion
We implemented Angular Material Components to our angular application which was created with ABP Framework. There is no blocker case of using angular libraries with the ABP framework.

215
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs

@ -26,415 +26,458 @@ namespace Volo.Abp.Domain.Repositories
#region Any/All
public static Task<bool> AnyAsync<T>(
public static async Task<bool> AnyAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AnyAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AnyAsync(queryable, predicate, cancellationToken);
}
public static Task<bool> AllAsync<T>(
public static async Task<bool> AllAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AllAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AllAsync(queryable, predicate, cancellationToken);
}
#endregion
#region Count/LongCount
public static Task<int> CountAsync<T>(
public static async Task<int> CountAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.CountAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.CountAsync(queryable, cancellationToken);
}
public static Task<int> CountAsync<T>(
public static async Task<int> CountAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.CountAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.CountAsync(queryable, predicate, cancellationToken);
}
public static Task<long> LongCountAsync<T>(
public static async Task<long> LongCountAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LongCountAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LongCountAsync(queryable, cancellationToken);
}
public static Task<long> LongCountAsync<T>(
public static async Task<long> LongCountAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LongCountAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LongCountAsync(queryable, predicate, cancellationToken);
}
#endregion
#region First/FirstOrDefault
public static Task<T> FirstAsync<T>(
public static async Task<T> FirstAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.FirstAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.FirstAsync(queryable, cancellationToken);
}
public static Task<T> FirstAsync<T>(
public static async Task<T> FirstAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.FirstAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.FirstAsync(queryable, predicate, cancellationToken);
}
public static Task<T> FirstOrDefaultAsync<T>(
public static async Task<T> FirstOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.FirstOrDefaultAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.FirstOrDefaultAsync(queryable, cancellationToken);
}
public static Task<T> FirstOrDefaultAsync<T>(
public static async Task<T> FirstOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.FirstOrDefaultAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.FirstOrDefaultAsync(queryable, predicate, cancellationToken);
}
#endregion
#region Last/LastOrDefault
public static Task<T> LastAsync<T>(
public static async Task<T> LastAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LastAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LastAsync(queryable, cancellationToken);
}
public static Task<T> LastAsync<T>(
public static async Task<T> LastAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LastAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LastAsync(queryable, predicate, cancellationToken);
}
public static Task<T> LastOrDefaultAsync<T>(
public static async Task<T> LastOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LastOrDefaultAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LastOrDefaultAsync(queryable, cancellationToken);
}
public static Task<T> LastOrDefaultAsync<T>(
public static async Task<T> LastOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.LastOrDefaultAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.LastOrDefaultAsync(queryable, predicate, cancellationToken);
}
#endregion
#region Single/SingleOrDefault
public static Task<T> SingleAsync<T>(
public static async Task<T> SingleAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SingleAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SingleAsync(queryable, cancellationToken);
}
public static Task<T> SingleAsync<T>(
public static async Task<T> SingleAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SingleAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SingleAsync(queryable, predicate, cancellationToken);
}
public static Task<T> SingleOrDefaultAsync<T>(
public static async Task<T> SingleOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SingleOrDefaultAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SingleOrDefaultAsync(queryable, cancellationToken);
}
public static Task<T> SingleOrDefaultAsync<T>(
public static async Task<T> SingleOrDefaultAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SingleOrDefaultAsync(repository, predicate, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SingleOrDefaultAsync(queryable, predicate, cancellationToken);
}
#endregion
#region Min
public static Task<T> MinAsync<T>(
public static async Task<T> MinAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.MinAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.MinAsync(queryable, cancellationToken);
}
public static Task<TResult> MinAsync<T, TResult>(
public static async Task<TResult> MinAsync<T, TResult>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.MinAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.MinAsync(queryable, selector, cancellationToken);
}
#endregion
#region Max
public static Task<T> MaxAsync<T>(
public static async Task<T> MaxAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.MaxAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.MaxAsync(queryable, cancellationToken);
}
public static Task<TResult> MaxAsync<T, TResult>(
public static async Task<TResult> MaxAsync<T, TResult>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.MaxAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.MaxAsync(queryable, selector, cancellationToken);
}
#endregion
#region Sum
public static Task<decimal> SumAsync<T>(
public static async Task<decimal> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<decimal?> SumAsync<T>(
public static async Task<decimal?> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<int> SumAsync<T>(
public static async Task<int> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<int?> SumAsync<T>(
public static async Task<int?> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<long> SumAsync<T>(
public static async Task<long> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<long?> SumAsync<T>(
public static async Task<long?> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<double> SumAsync<T>(
public static async Task<double> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<double?> SumAsync<T>(
public static async Task<double?> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<float> SumAsync<T>(
public static async Task<float> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, float>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
public static Task<float?> SumAsync<T>(
public static async Task<float?> SumAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.SumAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken);
}
#endregion
#region Average
public static Task<decimal> AverageAsync<T>(
public static async Task<decimal> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<decimal?> AverageAsync<T>(
public static async Task<decimal?> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double> AverageAsync<T>(
public static async Task<double> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double?> AverageAsync<T>(
public static async Task<double?> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double> AverageAsync<T>(
public static async Task<double> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double?> AverageAsync<T>(
public static async Task<double?> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double> AverageAsync<T>(
public static async Task<double> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<double?> AverageAsync<T>(
public static async Task<double?> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
public static Task<float?> AverageAsync<T>(
public static async Task<float?> AverageAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.AverageAsync(repository, selector, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken);
}
#endregion
#region ToList/Array
public static Task<List<T>> ToListAsync<T>(
public static async Task<List<T>> ToListAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.ToListAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.ToListAsync(queryable, cancellationToken);
}
public static Task<T[]> ToArrayAsync<T>(
public static async Task<T[]> ToArrayAsync<T>(
[NotNull] this IReadOnlyRepository<T> repository,
CancellationToken cancellationToken = default)
where T : class, IEntity
{
return repository.AsyncExecuter.ToArrayAsync(repository, cancellationToken);
var queryable = await repository.GetQueryableAsync();
return await repository.AsyncExecuter.ToArrayAsync(queryable, cancellationToken);
}
#endregion

67
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs

@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Uow;
@ -43,6 +46,65 @@ namespace Volo.Abp.Domain.Repositories
}
}
public static async Task HardDeleteAsync<TEntity>(
this IRepository<TEntity> repository,
Expression<Func<TEntity, bool>> predicate,
bool autoSave = false,
CancellationToken cancellationToken = default
)
where TEntity : class, IEntity, ISoftDelete
{
if (!(ProxyHelper.UnProxy(repository) is IUnitOfWorkManagerAccessor unitOfWorkManagerAccessor))
{
throw new AbpException($"The given repository (of type {repository.GetType().AssemblyQualifiedName}) should implement the {typeof(IUnitOfWorkManagerAccessor).AssemblyQualifiedName} interface in order to invoke the {nameof(HardDeleteAsync)} method!");
}
var uowManager = unitOfWorkManagerAccessor.UnitOfWorkManager;
if (uowManager == null)
{
throw new AbpException($"{nameof(unitOfWorkManagerAccessor.UnitOfWorkManager)} property of the given {nameof(repository)} object is null!");
}
if (uowManager.Current == null)
{
using (var uow = uowManager.Begin())
{
await HardDeleteWithUnitOfWorkAsync(repository, predicate, autoSave, cancellationToken, uowManager.Current);
await uow.CompleteAsync(cancellationToken);
}
}
else
{
await HardDeleteWithUnitOfWorkAsync(repository, predicate, autoSave, cancellationToken, uowManager.Current);
}
}
private static async Task HardDeleteWithUnitOfWorkAsync<TEntity>(
IRepository<TEntity> repository,
Expression<Func<TEntity, bool>> predicate,
bool autoSave,
CancellationToken cancellationToken, IUnitOfWork currentUow
)
where TEntity : class, IEntity, ISoftDelete
{
var hardDeleteEntities = (HashSet<IEntity>) currentUow.Items.GetOrAdd(
UnitOfWorkItemNames.HardDeletedEntities,
() => new HashSet<IEntity>()
);
List<TEntity> entities;
using (currentUow.ServiceProvider.GetRequiredService<IDataFilter<ISoftDelete>>().Disable())
{
entities = await repository.AsyncExecuter.ToListAsync((await repository.GetQueryableAsync()).Where(predicate), cancellationToken);
}
foreach (var entity in entities)
{
hardDeleteEntities.Add(entity);
await repository.DeleteAsync(entity, autoSave, cancellationToken);
}
}
public static async Task HardDeleteAsync<TEntity>(
this IBasicRepository<TEntity> repository,
TEntity entity,
@ -77,8 +139,8 @@ namespace Volo.Abp.Domain.Repositories
}
private static async Task HardDeleteWithUnitOfWorkAsync<TEntity>(
IBasicRepository<TEntity> repository,
TEntity entity,
IBasicRepository<TEntity> repository,
TEntity entity,
bool autoSave,
CancellationToken cancellationToken, IUnitOfWork currentUow
)
@ -90,7 +152,6 @@ namespace Volo.Abp.Domain.Repositories
);
hardDeleteEntities.Add(entity);
await repository.DeleteAsync(entity, autoSave, cancellationToken);
}
}

58
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HardDelete_Tests.cs

@ -30,8 +30,26 @@ namespace Volo.Abp.TestApp.Testing
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
await PersonRepository.HardDeleteAsync(douglas);
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
}
}
[Fact]
public async Task Should_HardDelete_Entities_With_Predicate()
{
await PersonRepository.HardDeleteAsync(x => x.Id == TestDataBuilder.UserDouglasId || x.Id == TestDataBuilder.UserJohnDeletedId);
using (DataFilter.Disable<ISoftDelete>())
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
var john = await PersonRepository.FindAsync(TestDataBuilder.UserJohnDeletedId);
john.ShouldBeNull();
}
}
[Fact]
@ -62,8 +80,44 @@ namespace Volo.Abp.TestApp.Testing
await uow.CompleteAsync();
}
using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
}
}
[Fact]
public async Task Should_HardDelete_Soft_Deleted_Entities_With_Predicate()
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
await PersonRepository.DeleteAsync(douglas);
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.IsDeleted.ShouldBeTrue();
douglas.DeletionTime.ShouldNotBeNull();
}
using (var uow = UnitOfWorkManager.Begin())
{
await PersonRepository.HardDeleteAsync(x => x.Id == TestDataBuilder.UserDouglasId || x.Id == TestDataBuilder.UserJohnDeletedId);
await uow.CompleteAsync();
}
using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
var john = await PersonRepository.FindAsync(TestDataBuilder.UserJohnDeletedId);
john.ShouldBeNull();
}
}
}
}

13
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs

@ -1,4 +1,5 @@
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.Security.Claims;
@ -12,21 +13,21 @@ namespace Volo.Abp.FeatureManagement
protected ICurrentPrincipalAccessor PrincipalAccessor { get; }
public EditionFeatureManagementProvider(
IFeatureManagementStore store,
ICurrentPrincipalAccessor principalAccessor)
IFeatureManagementStore store,
ICurrentPrincipalAccessor principalAccessor)
: base(store)
{
PrincipalAccessor = principalAccessor;
}
protected override string NormalizeProviderKey(string providerKey)
protected override Task<string> NormalizeProviderKeyAsync(string providerKey)
{
if (providerKey != null)
{
return providerKey;
return Task.FromResult(providerKey);
}
return PrincipalAccessor.Principal?.FindEditionId()?.ToString("N");
return Task.FromResult(PrincipalAccessor.Principal?.FindEditionId()?.ToString("N"));
}
}
}
}

10
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs

@ -21,22 +21,22 @@ namespace Volo.Abp.FeatureManagement
public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{
return await Store.GetOrNullAsync(feature.Name, Name, NormalizeProviderKey(providerKey));
return await Store.GetOrNullAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey));
}
public virtual async Task SetAsync(FeatureDefinition feature, string value, string providerKey)
{
await Store.SetAsync(feature.Name, value, Name, NormalizeProviderKey(providerKey));
await Store.SetAsync(feature.Name, value, Name, await NormalizeProviderKeyAsync(providerKey));
}
public virtual async Task ClearAsync(FeatureDefinition feature, string providerKey)
{
await Store.DeleteAsync(feature.Name, Name, NormalizeProviderKey(providerKey));
await Store.DeleteAsync(feature.Name, Name, await NormalizeProviderKeyAsync(providerKey));
}
protected virtual string NormalizeProviderKey(string providerKey)
protected virtual Task<string> NormalizeProviderKeyAsync(string providerKey)
{
return providerKey;
return Task.FromResult(providerKey);
}
}
}

11
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagementProvider.cs

@ -1,4 +1,5 @@
using Volo.Abp.DependencyInjection;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.MultiTenancy;
@ -18,14 +19,14 @@ namespace Volo.Abp.FeatureManagement
CurrentTenant = currentTenant;
}
protected override string NormalizeProviderKey(string providerKey)
protected override Task<string> NormalizeProviderKeyAsync(string providerKey)
{
if (providerKey != null)
{
return providerKey;
return Task.FromResult(providerKey);
}
return CurrentTenant.Id?.ToString();
return Task.FromResult(CurrentTenant.Id?.ToString());
}
}
}
}

Loading…
Cancel
Save