Browse Source

Update Entity-Framework-Core.md

pull/7382/head
Halil İbrahim Kalkan 6 years ago
parent
commit
a861f91c38
  1. 91
      docs/en/Entity-Framework-Core.md

91
docs/en/Entity-Framework-Core.md

@ -344,7 +344,7 @@ You have different options when you want to load the related entities while quer
#### Repository.WithDetails #### Repository.WithDetails
`IRepository.WithDetails(...)` can be used to include one relation collection/property to the query. `IRepository.WithDetailsAsync(...)` can be used to get an `IQueryable<T>` by including one relation collection/property.
**Example: Get an order with lines** **Example: Get an order with lines**
@ -355,7 +355,7 @@ using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
namespace MyCrm namespace AbpDemo.Orders
{ {
public class OrderManager : DomainService public class OrderManager : DomainService
{ {
@ -368,35 +368,39 @@ namespace MyCrm
public async Task TestWithDetails(Guid id) public async Task TestWithDetails(Guid id)
{ {
var query = _orderRepository //Get a IQueryable<T> by including sub collections
.WithDetails(x => x.Lines) var queryable = await _orderRepository.WithDetailsAsync(x => x.Lines);
.Where(x => x.Id == id);
//Apply additional LINQ extension methods
var query = queryable.Where(x => x.Id == id);
//Execute the query and get the result
var order = await AsyncExecuter.FirstOrDefaultAsync(query); var order = await AsyncExecuter.FirstOrDefaultAsync(query);
} }
} }
} }
```` ````
> `AsyncExecuter` is used to execute async LINQ extensions without depending on the EF Core. If you add EF Core NuGet package reference to your project, then you can directly use `await _orderRepository.WithDetails(x => x.Lines).FirstOrDefaultAsync()`. But, this time you depend on the EF Core in your domain layer. See the [repository document](Repositories.md) to learn more. > `AsyncExecuter` is used to execute async LINQ extensions without depending on the EF Core. If you add EF Core NuGet package reference to your project, then you can directly use `await query.FirstOrDefaultAsync()`. But, this time you depend on the EF Core in your domain layer. See the [repository document](Repositories.md) to learn more.
**Example: Get a list of orders with their lines** **Example: Get a list of orders with their lines**
````csharp ````csharp
public async Task TestWithDetails() public async Task TestWithDetails()
{ {
var query = _orderRepository //Get a IQueryable<T> by including sub collections
.WithDetails(x => x.Lines); var queryable = await _orderRepository.WithDetailsAsync(x => x.Lines);
var orders = await AsyncExecuter.ToListAsync(query); //Execute the query and get the result
var orders = await AsyncExecuter.ToListAsync(queryable);
} }
```` ````
> `WithDetails` method can get more than one expression parameter if you need to include more than one navigation property or collection. > `WithDetailsAsync` method can get more than one expression parameter if you need to include more than one navigation property or collection.
#### DefaultWithDetailsFunc #### DefaultWithDetailsFunc
If you don't pass any expression to the `WithDetails` method, then it includes all the details using the `DefaultWithDetailsFunc` option you provide. If you don't pass any expression to the `WithDetailsAsync` method, then it includes all the details using the `DefaultWithDetailsFunc` option you provide.
You can configure `DefaultWithDetailsFunc` for an entity in the `ConfigureServices` method of your [module](Module-Development-Basics.md) in your `EntityFrameworkCore` project. You can configure `DefaultWithDetailsFunc` for an entity in the `ConfigureServices` method of your [module](Module-Development-Basics.md) in your `EntityFrameworkCore` project.
@ -419,12 +423,15 @@ Then you can use the `WithDetails` without any parameter:
````csharp ````csharp
public async Task TestWithDetails() public async Task TestWithDetails()
{ {
var query = _orderRepository.WithDetails(); //Get a IQueryable<T> by including all sub collections
var orders = await AsyncExecuter.ToListAsync(query); var queryable = await _orderRepository.WithDetailsAsync();
//Execute the query and get the result
var orders = await AsyncExecuter.ToListAsync(queryable);
} }
```` ````
`WithDetails()` executes the expression you've setup as the `DefaultWithDetailsFunc`. `WithDetailsAsync()` executes the expression you've setup as the `DefaultWithDetailsFunc`.
#### Repository Get/Find Methods #### Repository Get/Find Methods
@ -466,7 +473,7 @@ public async Task TestWithDetails()
#### Alternatives #### Alternatives
The repository patters tries to encapsulate the EF Core, so your options are limited. If you need an advanced scenario, you can follow one of the options; The repository pattern tries to encapsulate the EF Core, so your options are limited. If you need an advanced scenario, you can follow one of the options;
* Create a custom repository method and use the complete EF Core API. * Create a custom repository method and use the complete EF Core API.
* Reference to the `Volo.Abp.EntityFrameworkCore` package from your project. In this way, you can directly use `Include` and `ThenInclude` in your code. * Reference to the `Volo.Abp.EntityFrameworkCore` package from your project. In this way, you can directly use `Include` and `ThenInclude` in your code.
@ -550,24 +557,15 @@ See also [lazy loading document](https://docs.microsoft.com/en-us/ef/core/queryi
In most cases, you want to hide EF Core APIs behind a repository (this is the main purpose of the repository pattern). However, if you want to access the `DbContext` instance over the repository, you can use `GetDbContext()` or `GetDbSet()` extension methods. Example: In most cases, you want to hide EF Core APIs behind a repository (this is the main purpose of the repository pattern). However, if you want to access the `DbContext` instance over the repository, you can use `GetDbContext()` or `GetDbSet()` extension methods. Example:
````csharp ````csharp
public class BookService public async Task TestAsync()
{ {
private readonly IRepository<Book, Guid> _bookRepository; var dbContext = await _orderRepository.GetDbContextAsync();
var dbSet = await _orderRepository.GetDbSetAsync();
public BookService(IRepository<Book, Guid> bookRepository) //var dbSet = dbContext.Set<Order>(); //Alternative, when you have the DbContext
{
_bookRepository = bookRepository;
}
public void Foo()
{
DbContext dbContext = _bookRepository.GetDbContext();
DbSet<Book> books = _bookRepository.GetDbSet();
}
} }
```` ````
* `GetDbContext` returns a `DbContext` reference instead of `BookStoreDbContext`. You can cast it, however in most cases you don't need it. * `GetDbContextAsync` returns a `DbContext` reference instead of `BookStoreDbContext`. You can cast it if you need. However, you don't need it in most cases.
> Important: You must reference to the `Volo.Abp.EntityFrameworkCore` package from the project you want to access to the `DbContext`. This breaks encapsulation, but this is what you want in that case. > Important: You must reference to the `Volo.Abp.EntityFrameworkCore` package from the project you want to access to the `DbContext`. This breaks encapsulation, but this is what you want in that case.
@ -742,32 +740,36 @@ If you have better logic or using an external library for bulk operations, you c
- You may use example template below: - You may use example template below:
```csharp ```csharp
public class MyCustomEfCoreBulkOperationProvider : IEfCoreBulkOperationProvider, ITransientDependency public class MyCustomEfCoreBulkOperationProvider
{ : IEfCoreBulkOperationProvider, ITransientDependency
public async Task DeleteManyAsync<TDbContext, TEntity>(IEfCoreRepository<TEntity> repository, {
IEnumerable<TEntity> entities, public async Task DeleteManyAsync<TDbContext, TEntity>(
bool autoSave, IEfCoreRepository<TEntity> repository,
CancellationToken cancellationToken) IEnumerable<TEntity> entities,
bool autoSave,
CancellationToken cancellationToken)
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity where TEntity : class, IEntity
{ {
// Your logic here. // Your logic here.
} }
public async Task InsertManyAsync<TDbContext, TEntity>(IEfCoreRepository<TEntity> repository, public async Task InsertManyAsync<TDbContext, TEntity>(
IEnumerable<TEntity> entities, IEfCoreRepository<TEntity> repository,
bool autoSave, IEnumerable<TEntity> entities,
CancellationToken cancellationToken) bool autoSave,
CancellationToken cancellationToken)
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity where TEntity : class, IEntity
{ {
// Your logic here. // Your logic here.
} }
public async Task UpdateManyAsync<TDbContext, TEntity>(IEfCoreRepository<TEntity> repository, public async Task UpdateManyAsync<TDbContext, TEntity>(
IEnumerable<TEntity> entities, IEfCoreRepository<TEntity> repository,
bool autoSave, IEnumerable<TEntity> entities,
CancellationToken cancellationToken) bool autoSave,
CancellationToken cancellationToken)
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity where TEntity : class, IEntity
{ {
@ -779,3 +781,4 @@ public class MyCustomEfCoreBulkOperationProvider : IEfCoreBulkOperationProvider,
## See Also ## See Also
* [Entities](Entities.md) * [Entities](Entities.md)
* [Repositories](Repositories.md)

Loading…
Cancel
Save