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