mirror of https://github.com/abpframework/abp.git
14 changed files with 278 additions and 55 deletions
@ -0,0 +1,34 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Query.Internal; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Linq; |
||||
|
|
||||
|
namespace Volo.Abp.EntityFrameworkCore |
||||
|
{ |
||||
|
public class EfCoreAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency |
||||
|
{ |
||||
|
public bool CanExecute<T>(IQueryable<T> queryable) |
||||
|
{ |
||||
|
return queryable.Provider is EntityQueryProvider; |
||||
|
} |
||||
|
|
||||
|
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return queryable.CountAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return queryable.ToListAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return queryable.FirstOrDefaultAsync(cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Linq; |
||||
|
using MongoDB.Driver; |
||||
|
using MongoDB.Driver.Linq; |
||||
|
|
||||
|
namespace Volo.Abp.MongoDB |
||||
|
{ |
||||
|
public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency |
||||
|
{ |
||||
|
public bool CanExecute<T>(IQueryable<T> queryable) |
||||
|
{ |
||||
|
return queryable.Provider.GetType().Namespace?.StartsWith("MongoDB") ?? false; |
||||
|
} |
||||
|
|
||||
|
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return ((IMongoQueryable<T>) queryable).CountAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return ((IMongoQueryable<T>) queryable).ToListAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return ((IMongoQueryable<T>) queryable).FirstOrDefaultAsync(cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Linq |
||||
|
{ |
||||
|
public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ITransientDependency |
||||
|
{ |
||||
|
protected IEnumerable<IAsyncQueryableProvider> Providers { get; } |
||||
|
|
||||
|
public AsyncQueryableExecuter(IEnumerable<IAsyncQueryableProvider> providers) |
||||
|
{ |
||||
|
Providers = providers; |
||||
|
} |
||||
|
|
||||
|
public virtual Task<int> CountAsync<T>( |
||||
|
IQueryable<T> queryable, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var provider = FindProvider(queryable); |
||||
|
return provider != null |
||||
|
? provider.CountAsync(queryable, cancellationToken) |
||||
|
: Task.FromResult(queryable.Count()); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<List<T>> ToListAsync<T>( |
||||
|
IQueryable<T> queryable, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var provider = FindProvider(queryable); |
||||
|
return provider != null |
||||
|
? provider.ToListAsync(queryable, cancellationToken) |
||||
|
: Task.FromResult(queryable.ToList()); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<T> FirstOrDefaultAsync<T>( |
||||
|
IQueryable<T> queryable, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var provider = FindProvider(queryable); |
||||
|
return provider != null |
||||
|
? provider.FirstOrDefaultAsync(queryable, cancellationToken) |
||||
|
: Task.FromResult(queryable.FirstOrDefault()); |
||||
|
} |
||||
|
|
||||
|
protected virtual IAsyncQueryableProvider FindProvider<T>(IQueryable<T> queryable) |
||||
|
{ |
||||
|
return Providers.FirstOrDefault(p => p.CanExecute(queryable)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,37 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace Volo.Abp.Linq |
|
||||
{ |
|
||||
public class DefaultAsyncQueryableExecuter : IAsyncQueryableExecuter |
|
||||
{ |
|
||||
public static DefaultAsyncQueryableExecuter Instance { get; } = new DefaultAsyncQueryableExecuter(); |
|
||||
|
|
||||
private DefaultAsyncQueryableExecuter() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public Task<int> CountAsync<T>(IQueryable<T> queryable) |
|
||||
{ |
|
||||
return Task.FromResult(queryable.Count()); |
|
||||
} |
|
||||
|
|
||||
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable) |
|
||||
{ |
|
||||
return Task.FromResult(queryable.ToList()); |
|
||||
} |
|
||||
|
|
||||
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable) |
|
||||
{ |
|
||||
return Task.FromResult(queryable.FirstOrDefault()); |
|
||||
} |
|
||||
|
|
||||
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken) |
|
||||
{ |
|
||||
return Task.FromResult(queryable.FirstOrDefault()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Linq |
||||
|
{ |
||||
|
public interface IAsyncQueryableProvider |
||||
|
{ |
||||
|
bool CanExecute<T>(IQueryable<T> queryable); |
||||
|
|
||||
|
Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.TestApp.Domain; |
||||
|
using Volo.Abp.Uow; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.EntityFrameworkCore |
||||
|
{ |
||||
|
public class EfCoreAsyncQueryableProvider_Tests : EntityFrameworkCoreTestBase |
||||
|
{ |
||||
|
private readonly IRepository<Person, Guid> _personRepository; |
||||
|
private readonly EfCoreAsyncQueryableProvider _efCoreAsyncQueryableProvider; |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
|
||||
|
public EfCoreAsyncQueryableProvider_Tests() |
||||
|
{ |
||||
|
_personRepository = GetRequiredService<IRepository<Person, Guid>>(); |
||||
|
_efCoreAsyncQueryableProvider = GetRequiredService<EfCoreAsyncQueryableProvider>(); |
||||
|
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Accept_EfCore_Related_Queries() |
||||
|
{ |
||||
|
var query = _personRepository.Where(p => p.Age > 0); |
||||
|
|
||||
|
_efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Not_Accept_Other_Providers() |
||||
|
{ |
||||
|
var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); |
||||
|
|
||||
|
_efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Execute_Queries() |
||||
|
{ |
||||
|
using (var uow = _unitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
var query = _personRepository.Where(p => p.Age > 0); |
||||
|
|
||||
|
(await _efCoreAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); |
||||
|
(await _efCoreAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); |
||||
|
(await _efCoreAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); |
||||
|
|
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.TestApp.Domain; |
||||
|
using Volo.Abp.Uow; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.MongoDB |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class MongoDbAsyncQueryableProvider_Tests : MongoDbTestBase |
||||
|
{ |
||||
|
private readonly IRepository<Person, Guid> _personRepository; |
||||
|
private readonly MongoDbAsyncQueryableProvider _mongoDbAsyncQueryableProvider; |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
|
||||
|
public MongoDbAsyncQueryableProvider_Tests() |
||||
|
{ |
||||
|
_personRepository = GetRequiredService<IRepository<Person, Guid>>(); |
||||
|
_mongoDbAsyncQueryableProvider = GetRequiredService<MongoDbAsyncQueryableProvider>(); |
||||
|
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Accept_MongoDb_Related_Queries() |
||||
|
{ |
||||
|
var query = _personRepository.Where(p => p.Age > 0); |
||||
|
|
||||
|
_mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Not_Accept_Other_Providers() |
||||
|
{ |
||||
|
var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); |
||||
|
|
||||
|
_mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Execute_Queries() |
||||
|
{ |
||||
|
using (var uow = _unitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
var query = _personRepository.Where(p => p.Age > 0).OrderBy(p => p.Name); |
||||
|
|
||||
|
(await _mongoDbAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); |
||||
|
(await _mongoDbAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); |
||||
|
(await _mongoDbAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); |
||||
|
|
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue