Update docs for async queryable usage.

pull/7393/head
Halil İbrahim Kalkan 5 years ago
parent f3107749b7
commit 06284c44f8

@ -43,12 +43,14 @@ public class Book : AggregateRoot<Guid>
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException($"name can not be empty or white space!");
throw new ArgumentException(
$"name can not be empty or white space!");
}
if (name.Length > MaxNameLength)
{
throw new ArgumentException($"name can not be longer than {MaxNameLength} chars!");
throw new ArgumentException(
$"name can not be longer than {MaxNameLength} chars!");
}
return name;
@ -349,8 +351,9 @@ public class DistrictAppService
protected async override Task<District> GetEntityByIdAsync(DistrictKey id)
{
var queryable = await Repository.GetQueryableAsync();
return await AsyncQueryableExecuter.FirstOrDefaultAsync(
Repository.Where(d => d.CityId == id.CityId && d.Name == id.Name)
queryable.Where(d => d.CityId == id.CityId && d.Name == id.Name)
);
}
}

@ -184,7 +184,7 @@ public class PersonAppService : ApplicationService, IPersonAppService
}
````
ABP Framework's repository doesn't have this method. Instead, it implements the `IQueryable` itself. So, you can directly use LINQ on the repository:
ABP Framework's repository have `GetQueryableAsync` instead:
````csharp
public class PersonAppService : ApplicationService, IPersonAppService
@ -198,14 +198,15 @@ public class PersonAppService : ApplicationService, IPersonAppService
public async Task DoIt()
{
var people = await _personRepository
var queryable = await _personRepository.GetQueryableAsync();
var people = await queryable
.Where(p => p.BirthYear > 2000) //Use LINQ extension methods
.ToListAsync();
}
}
````
> Note that in order to use the async LINQ extension methods (like `ToListAsync` here), you may need to depend on the database provider (like EF Core) since these methods are defined in the database provider package, they are not standard LINQ methods.
> Note that in order to use the async LINQ extension methods (like `ToListAsync` here), you may need to depend on the database provider (like EF Core) since these methods are defined in the database provider package, they are not standard LINQ methods. See the [repository document](Repositories.md) for alternative approaches for async query execution.
#### FirstOrDefault(predicate), Single()... Methods

@ -754,7 +754,8 @@ namespace IssueTracking.Issues
{
var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30));
return await DbSet.Where(i =>
var dbSet = await GetDbSetAsync();
return await dbSet.Where(i =>
//Open
!i.IsClosed &&
@ -906,7 +907,8 @@ public class EfCoreIssueRepository :
public async Task<List<Issue>> GetIssuesAsync(ISpecification<Issue> spec)
{
return await DbSet
var dbSet = await GetDbSetAsync();
return await dbSet
.Where(spec.ToExpression())
.ToListAsync();
}
@ -952,8 +954,9 @@ public class IssueAppService : ApplicationService, IIssueAppService
public async Task DoItAsync()
{
var queryable = await _issueRepository.GetQueryableAsync();
var issues = AsyncExecuter.ToListAsync(
_issueRepository.Where(new InActiveIssueSpecification())
queryable.Where(new InActiveIssueSpecification())
);
}
}
@ -996,8 +999,9 @@ public class IssueAppService : ApplicationService, IIssueAppService
public async Task DoItAsync(Guid milestoneId)
{
var queryable = await _issueRepository.GetQueryableAsync();
var issues = AsyncExecuter.ToListAsync(
_issueRepository
queryable
.Where(
new InActiveIssueSpecification()
.And(new MilestoneSpecification(milestoneId))

@ -222,7 +222,8 @@ public class PersonRepository : EfCoreRepository<MyDbContext, Person, Guid>, IPe
public async Task<Person> FindByNameAsync(string name)
{
return await DbContext.Set<Person>()
var dbSet = await GetDbSetAsync();
return await dbSet.Set<Person>()
.Where(p => p.Name == name)
.FirstOrDefaultAsync();
}
@ -235,12 +236,13 @@ You can directly access the data access provider (`DbContext` in this case) to p
## IQueryable & Async Operations
`IRepository` inherits from `IQueryable`, that means you can **directly use LINQ extension methods** on it, as shown in the example of the "*Generic Repositories*" section above.
`IRepository` provides `GetQueryableAsync()` to obtain an `IQueryable`, that means you can **directly use LINQ extension methods** on it, as shown in the example of the "*Querying / LINQ over the Repositories*" section above.
**Example: Using the `Where(...)` and the `ToList()` extension methods**
````csharp
var people = _personRepository
var queryable = await _personRepository.GetQueryableAsync();
var people = queryable
.Where(p => p.Name.Contains(nameFilter))
.ToList();
````
@ -269,7 +271,8 @@ When you add the NuGet package to your project, you can take full power of the E
**Example: Directly using the `ToListAsync()` after adding the EF Core package**
````csharp
var people = _personRepository
var queryable = await _personRepository.GetQueryableAsync();
var people = queryable
.Where(p => p.Name.Contains(nameFilter))
.ToListAsync();
````
@ -285,7 +288,8 @@ If you are using [MongoDB](MongoDB.md), you need to add the [Volo.Abp.MongoDB](h
**Example: Cast `IQueryable<T>` to `IMongoQueryable<T>` and use `ToListAsync()`**
````csharp
var people = ((IMongoQueryable<Person>)_personRepository
var queryable = await _personRepository.GetQueryableAsync();
var people = ((IMongoQueryable<Person>) queryable
.Where(p => p.Name.Contains(nameFilter)))
.ToListAsync();
````
@ -312,10 +316,11 @@ The standard LINQ extension methods are supported: *AllAsync, AnyAsync, AverageA
This approach still **has a limitation**. You need to call the extension method directly on the repository object. For example, the below usage is **not supported**:
```csharp
var count = await _bookRepository.Where(x => x.Name.Contains("A")).CountAsync();
var queryable = await _bookRepository.GetQueryableAsync();
var count = await queryable.Where(x => x.Name.Contains("A")).CountAsync();
```
This is because the object returned from the `Where` method is not a repository object, it is a standard `IQueryable` interface. See the other options for such cases.
This is because the `CountAsync()` method in this example is called on a `IQueryable` interface, not on the repository object. See the other options for such cases.
This method is suggested **wherever possible**.
@ -352,8 +357,11 @@ namespace AbpDemo
public async Task<ListResultDto<ProductDto>> GetListAsync(string name)
{
//Obtain the IQueryable<T>
var queryable = await _productRepository.GetQueryableAsync();
//Create the query
var query = _productRepository
var query = queryable
.Where(p => p.Name.Contains(name))
.OrderBy(p => p.Name);

@ -122,7 +122,8 @@ namespace MyProject
public async Task<List<Customer>> GetCustomersCanBuyAlcohol()
{
var query = _customerRepository.Where(
var queryable = await _customerRepository.GetQueryableAsync();
var query = queryable.Where(
new Age18PlusCustomerSpecification().ToExpression()
);
@ -137,7 +138,8 @@ namespace MyProject
Actually, using the `ToExpression()` method is not necessary since the specifications are automatically casted to Expressions. This would also work:
````csharp
var query = _customerRepository.Where(
var queryable = await _customerRepository.GetQueryableAsync();
var query = queryable.Where(
new Age18PlusCustomerSpecification()
);
````

Loading…
Cancel
Save