Browse Source

Merge pull request #17207 from abpframework/FilterQueryable

Add `FilterQueryable` method to `IMongoDbRepositoryFilterer`.
pull/17234/head
liangshiwei 3 years ago
committed by GitHub
parent
commit
7758dddf27
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      docs/en/Data-Filtering.md
  2. 10
      docs/zh-Hans/Data-Filtering.md
  3. 3
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepositoryFilterer.cs
  4. 28
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
  5. 10
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepositoryFilterer.cs
  6. 53
      framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MongoDbRepositoryFilterer_Tests.cs

10
docs/en/Data-Filtering.md

@ -255,7 +255,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
ABP abstracts the `IMongoDbRepositoryFilterer` interface to implement data filtering for the [MongoDB Integration](MongoDB.md), it works only if you use the repositories properly. Otherwise, you should manually filter the data.
Currently, the best way to implement a data filter for the MongoDB integration is to create a derived class of `MongoDbRepositoryFilterer` and override `AddGlobalFilters`. Example:
Currently, the best way to implement a data filter for the MongoDB integration is to create a derived class of `MongoDbRepositoryFilterer` and override `FilterQueryable`. Example:
````csharp
[ExposeServices(typeof(IMongoDbRepositoryFilterer<Book, Guid>))]
@ -268,14 +268,14 @@ public class BookMongoDbRepositoryFilterer : MongoDbRepositoryFilterer<Book, Gui
{
}
public override void AddGlobalFilters(List<FilterDefinition<Book>> filters)
public override TQueryable FilterQueryable<TQueryable>(TQueryable query)
{
base.AddGlobalFilters(filters);
if (DataFilter.IsEnabled<IIsActive>())
{
filters.Add(Builders<Book>.Filter.Eq(e => ((IIsActive)e).IsActive, true));
return (TQueryable)query.Where(x => x.IsActive);
}
return base.FilterQueryable(query);
}
}
````

10
docs/zh-Hans/Data-Filtering.md

@ -190,7 +190,7 @@ protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntit
ABP抽象了 `IMongoDbRepositoryFilterer` 接口为[MongoDB 集成](MongoDB.md)实现数据过滤, 只有正确的使用仓储,它才会工作. 否则你需要手动过滤数据.
目前为MongoDB集成实现数据过滤的最佳方法是重写派生自 `MongoDbRepositoryFilterer` 基类的 `AddGlobalFilters` 方法:
目前为MongoDB集成实现数据过滤的最佳方法是重写派生自 `MongoDbRepositoryFilterer` 基类的 `FilterQueryable` 方法:
````csharp
[ExposeServices(typeof(IMongoDbRepositoryFilterer<Book, Guid>))]
@ -203,14 +203,14 @@ public class BookMongoDbRepositoryFilterer : MongoDbRepositoryFilterer<Book, Gui
{
}
public override void AddGlobalFilters(List<FilterDefinition<Book>> filters)
public override TQueryable FilterQueryable<TQueryable>(TQueryable query)
{
base.AddGlobalFilters(filters);
if (DataFilter.IsEnabled<IIsActive>())
{
filters.Add(Builders<Book>.Filter.Eq(e => ((IIsActive)e).IsActive, true));
return (TQueryable)query.Where(x => x.IsActive);
}
return base.FilterQueryable(query);
}
}
````

3
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepositoryFilterer.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using Volo.Abp.Domain.Entities;
@ -8,6 +9,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB;
public interface IMongoDbRepositoryFilterer<TEntity> where TEntity : class, IEntity
{
Task AddGlobalFiltersAsync(List<FilterDefinition<TEntity>> filters);
TQueryable FilterQueryable<TQueryable>(TQueryable query) where TQueryable : IQueryable<TEntity>;
}
public interface IMongoDbRepositoryFilterer<TEntity, TKey> : IMongoDbRepositoryFilterer<TEntity> where TEntity : class, IEntity<TKey>

28
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs

@ -4,7 +4,6 @@ using MongoDB.Driver.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
@ -99,6 +98,8 @@ public class MongoDbRepository<TMongoDbContext, TEntity>
public IMongoDbBulkOperationProvider BulkOperationProvider => LazyServiceProvider.LazyGetService<IMongoDbBulkOperationProvider>();
public IMongoDbRepositoryFilterer<TEntity> RepositoryFilterer => LazyServiceProvider.LazyGetService<IMongoDbRepositoryFilterer<TEntity>>();
public MongoDbRepository(IMongoDbContextProvider<TMongoDbContext> dbContextProvider)
{
DbContextProvider = dbContextProvider;
@ -738,6 +739,15 @@ public class MongoDbRepository<TMongoDbContext, TEntity>
{
throw new AbpDbConcurrencyException("Database operation expected to affect 1 row but actually affected 0 row. Data may have been modified or deleted since entities were loaded. This exception has been thrown on optimistic concurrency check.");
}
protected override TQueryable ApplyDataFilters<TQueryable, TOtherEntity>(TQueryable query)
{
if (typeof(TOtherEntity) == typeof(TEntity))
{
return base.ApplyDataFilters<TQueryable, TOtherEntity>((TQueryable)RepositoryFilterer.FilterQueryable(query.As<IQueryable<TEntity>>()));
}
return base.ApplyDataFilters<TQueryable, TOtherEntity>(query);
}
}
public class MongoDbRepository<TMongoDbContext, TEntity, TKey>
@ -746,7 +756,7 @@ public class MongoDbRepository<TMongoDbContext, TEntity, TKey>
where TMongoDbContext : IAbpMongoDbContext
where TEntity : class, IEntity<TKey>
{
public IMongoDbRepositoryFilterer<TEntity, TKey> RepositoryFilterer { get; set; }
public IMongoDbRepositoryFilterer<TEntity, TKey> RepositoryFiltererWithKey => LazyServiceProvider.LazyGetService<IMongoDbRepositoryFilterer<TEntity, TKey>>();
public MongoDbRepository(IMongoDbContextProvider<TMongoDbContext> dbContextProvider)
: base(dbContextProvider)
@ -798,13 +808,23 @@ public class MongoDbRepository<TMongoDbContext, TEntity, TKey>
await DeleteManyAsync(entities, autoSave, cancellationToken);
}
protected override TQueryable ApplyDataFilters<TQueryable, TOtherEntity>(TQueryable query)
{
if (typeof(TOtherEntity) == typeof(TEntity))
{
return base.ApplyDataFilters<TQueryable, TOtherEntity>((TQueryable)RepositoryFiltererWithKey.FilterQueryable(query.As<IQueryable<TEntity>>()));
}
return base.ApplyDataFilters<TQueryable, TOtherEntity>(query);
}
protected async override Task<FilterDefinition<TEntity>> CreateEntityFilterAsync(TEntity entity, bool withConcurrencyStamp = false, string concurrencyStamp = null)
{
return await RepositoryFilterer.CreateEntityFilterAsync(entity, withConcurrencyStamp, concurrencyStamp);
return await RepositoryFiltererWithKey.CreateEntityFilterAsync(entity, withConcurrencyStamp, concurrencyStamp);
}
protected async override Task<FilterDefinition<TEntity>> CreateEntitiesFilterAsync(IEnumerable<TEntity> entities, bool withConcurrencyStamp = false)
{
return await RepositoryFilterer.CreateEntitiesFilterAsync(entities, withConcurrencyStamp);
return await RepositoryFiltererWithKey.CreateEntitiesFilterAsync(entities, withConcurrencyStamp);
}
}

10
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepositoryFilterer.cs

@ -36,6 +36,11 @@ public class MongoDbRepositoryFilterer<TEntity> : IMongoDbRepositoryFilterer<TEn
return Task.CompletedTask;
}
public virtual TQueryable FilterQueryable<TQueryable>(TQueryable query) where TQueryable : IQueryable<TEntity>
{
return query;
}
}
public class MongoDbRepositoryFilterer<TEntity, TKey> : MongoDbRepositoryFilterer<TEntity>,
@ -99,4 +104,9 @@ public class MongoDbRepositoryFilterer<TEntity, TKey> : MongoDbRepositoryFiltere
return Builders<TEntity>.Filter.And(filters);
}
public virtual TQueryable FilterQueryable<TQueryable>(TQueryable query) where TQueryable : IQueryable<TEntity>
{
return query;
}
}

53
framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MongoDbRepositoryFilterer_Tests.cs

@ -0,0 +1,53 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TestApp.Domain;
using Xunit;
namespace Volo.Abp.MongoDB.DataFiltering;
[Collection(MongoTestCollection.Name)]
public class MongoDbAsyncQueryableProvider_Tests : MongoDbTestBase
{
private readonly IRepository<City, Guid> _personRepository;
protected override void AfterAddApplication(IServiceCollection services)
{
services.AddTransient<IMongoDbRepositoryFilterer<City, Guid>, TestFilterQueryable>();
base.AfterAddApplication(services);
}
public MongoDbAsyncQueryableProvider_Tests()
{
_personRepository = GetRequiredService<IRepository<City, Guid>>();
}
[Fact]
public async Task Test()
{
var cities = await _personRepository.GetListAsync();
cities.Count.ShouldBe(1);
cities[0].Name.ShouldBe("Istanbul");
}
}
public class TestFilterQueryable : MongoDbRepositoryFilterer<City, Guid>
{
public TestFilterQueryable(
IDataFilter dataFilter,
ICurrentTenant currentTenant) :
base(dataFilter, currentTenant)
{
}
public override TQueryable FilterQueryable<TQueryable>(TQueryable query)
{
return (TQueryable)query.Where(p => p.Name == "Istanbul");
}
}
Loading…
Cancel
Save