Browse Source

Update docs for async queryable usage.

pull/7393/head
Halil İbrahim Kalkan 6 years ago
parent
commit
06284c44f8
  1. 9
      docs/en/Application-Services.md
  2. 7
      docs/en/AspNet-Boilerplate-Migration-Guide.md
  3. 12
      docs/en/Domain-Driven-Design-Implementation-Guide.md
  4. 24
      docs/en/Repositories.md
  5. 6
      docs/en/Specifications.md

9
docs/en/Application-Services.md

@ -43,12 +43,14 @@ public class Book : AggregateRoot<Guid>
{ {
if (string.IsNullOrWhiteSpace(name)) 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) 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; return name;
@ -349,8 +351,9 @@ public class DistrictAppService
protected async override Task<District> GetEntityByIdAsync(DistrictKey id) protected async override Task<District> GetEntityByIdAsync(DistrictKey id)
{ {
var queryable = await Repository.GetQueryableAsync();
return await AsyncQueryableExecuter.FirstOrDefaultAsync( 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)
); );
} }
} }

7
docs/en/AspNet-Boilerplate-Migration-Guide.md

@ -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 ````csharp
public class PersonAppService : ApplicationService, IPersonAppService public class PersonAppService : ApplicationService, IPersonAppService
@ -198,14 +198,15 @@ public class PersonAppService : ApplicationService, IPersonAppService
public async Task DoIt() 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 .Where(p => p.BirthYear > 2000) //Use LINQ extension methods
.ToListAsync(); .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 #### FirstOrDefault(predicate), Single()... Methods

12
docs/en/Domain-Driven-Design-Implementation-Guide.md

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

24
docs/en/Repositories.md

@ -222,7 +222,8 @@ public class PersonRepository : EfCoreRepository<MyDbContext, Person, Guid>, IPe
public async Task<Person> FindByNameAsync(string name) 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) .Where(p => p.Name == name)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
} }
@ -235,12 +236,13 @@ You can directly access the data access provider (`DbContext` in this case) to p
## IQueryable & Async Operations ## 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** **Example: Using the `Where(...)` and the `ToList()` extension methods**
````csharp ````csharp
var people = _personRepository var queryable = await _personRepository.GetQueryableAsync();
var people = queryable
.Where(p => p.Name.Contains(nameFilter)) .Where(p => p.Name.Contains(nameFilter))
.ToList(); .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** **Example: Directly using the `ToListAsync()` after adding the EF Core package**
````csharp ````csharp
var people = _personRepository var queryable = await _personRepository.GetQueryableAsync();
var people = queryable
.Where(p => p.Name.Contains(nameFilter)) .Where(p => p.Name.Contains(nameFilter))
.ToListAsync(); .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()`** **Example: Cast `IQueryable<T>` to `IMongoQueryable<T>` and use `ToListAsync()`**
````csharp ````csharp
var people = ((IMongoQueryable<Person>)_personRepository var queryable = await _personRepository.GetQueryableAsync();
var people = ((IMongoQueryable<Person>) queryable
.Where(p => p.Name.Contains(nameFilter))) .Where(p => p.Name.Contains(nameFilter)))
.ToListAsync(); .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**: 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 ```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**. This method is suggested **wherever possible**.
@ -352,8 +357,11 @@ namespace AbpDemo
public async Task<ListResultDto<ProductDto>> GetListAsync(string name) public async Task<ListResultDto<ProductDto>> GetListAsync(string name)
{ {
//Obtain the IQueryable<T>
var queryable = await _productRepository.GetQueryableAsync();
//Create the query //Create the query
var query = _productRepository var query = queryable
.Where(p => p.Name.Contains(name)) .Where(p => p.Name.Contains(name))
.OrderBy(p => p.Name); .OrderBy(p => p.Name);

6
docs/en/Specifications.md

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

Loading…
Cancel
Save