Skip to content

Commit 46c4f02

Browse files
authored
[DataGrid] Allow EntityFrameworkAsyncQueryExecutor configuration #3272
* Implement feature request #3269 * Implement alternative solution to making EntityFrameworkAsyncQueryExecutor inheritable in order to be able to handle specific Exceptions. Thanks @miguelhasse * Edit readme
1 parent a24c3e4 commit 46c4f02

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

src/Extensions/DataGrid.EntityFrameworkAdapter/EntityFrameworkAdapterServiceCollectionExtensions.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
// ------------------------------------------------------------------------
2+
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------------------
4+
15
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter;
26
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;
37

8+
#pragma warning disable IDE0130 // Namespace does not match folder structure
49
namespace Microsoft.Extensions.DependencyInjection;
10+
#pragma warning restore IDE0130 // Namespace does not match folder structure
511

612
/// <summary>
713
/// Provides extension methods to configure <see cref="IAsyncQueryExecutor"/> on a <see cref="IServiceCollection"/>.
@@ -12,8 +18,9 @@ public static class EntityFrameworkAdapterServiceCollectionExtensions
1218
/// Registers an Entity Framework aware implementation of <see cref="IAsyncQueryExecutor"/>.
1319
/// </summary>
1420
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
15-
public static void AddDataGridEntityFrameworkAdapter(this IServiceCollection services)
21+
/// <param name="ignoreException">A function to determine whether to ignore exceptions.</param>
22+
public static void AddDataGridEntityFrameworkAdapter(this IServiceCollection services, Func<Exception, bool>? ignoreException = null)
1623
{
17-
services.AddScoped<IAsyncQueryExecutor, EntityFrameworkAsyncQueryExecutor>();
24+
services.AddScoped<IAsyncQueryExecutor, EntityFrameworkAsyncQueryExecutor>(sp => new EntityFrameworkAsyncQueryExecutor(ignoreException));
1825
}
1926
}

src/Extensions/DataGrid.EntityFrameworkAdapter/EntityFrameworkAsyncQueryExecutor.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
1+
// ------------------------------------------------------------------------
2+
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------------------
4+
15
using Microsoft.EntityFrameworkCore;
26
using Microsoft.EntityFrameworkCore.Query;
37
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;
48

59
namespace Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter;
610

7-
internal class EntityFrameworkAsyncQueryExecutor : IAsyncQueryExecutor, IDisposable
11+
/// <summary>
12+
/// An <see cref="IAsyncQueryExecutor"/> implementation for Entity Framework Core.
13+
/// </summary>
14+
internal class EntityFrameworkAsyncQueryExecutor(Func<Exception, bool>? ignoreException = null) : IAsyncQueryExecutor, IDisposable
815
{
916
private readonly SemaphoreSlim _lock = new(1);
1017

18+
/// <inheritdoc />
1119
public bool IsSupported<T>(IQueryable<T> queryable)
1220
=> queryable.Provider is IAsyncQueryProvider;
1321

22+
/// <inheritdoc />
1423
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken)
1524
=> ExecuteAsync(() => queryable.CountAsync(cancellationToken));
1625

26+
/// <inheritdoc />
1727
public Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken)
1828
=> ExecuteAsync(() => queryable.ToArrayAsync(cancellationToken));
1929

@@ -36,6 +46,10 @@ private async Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> operation)
3646
{
3747
return default!;
3848
}
49+
catch (Exception ex) when (ignoreException?.Invoke(ex) == true)
50+
{
51+
return default!;
52+
}
3953
}
4054

4155
void IDisposable.Dispose() => _lock.Dispose();

src/Extensions/DataGrid.EntityFrameworkAdapter/README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,27 @@ Install the package by running the command:
2828
```
2929
dotnet add package Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter
3030
```
31-
3231
## Usage
33-
In your Program.cs file you need to add the following:
32+
When using the provided implementation, you need to add add the following in the `Program.cs` file:
33+
3434
```
3535
builder.Services.AddDataGridEntityFrameworkAdapter();
3636
```
3737

38+
## Changing the adapter's behavior
39+
Starting with v4.11.4, the `EntityFrameworkAsyncQueryExecutor` exposes a way to ignore exceptions which may occur during query execution.
40+
This can be useful when you want to handle exceptions in a custom way, for example, by logging them. To ignore exceptions, you can
41+
supply a `Func<Exception, bool>` to the `IgnoreException` property of the `EntityFrameworkAsyncQueryExecutor` instance. The function
42+
should return `true` if the exception should be ignored and `false` otherwise. An example:
43+
```csharp
44+
builder.Services.AddFluentUIComponents()
45+
.AddDataGridEntityFrameworkAdapter(ex => ex is SqlException sqlEx
46+
&& sqlEx.Errors.OfType<SqlError>().Any(e => (e.Class == 11 && e.Number == 0) || (e.Class == 16 && e.Number == 3204)));
47+
```
48+
49+
For more information see also https://github.com/microsoft/fluentui-blazor/issues/3269.
50+
51+
3852
## Support
3953
The Microsoft Fluent UI Blazor library is an open source project and is **not** an official part of ASP.NET Core, which means it’s **not** officially
4054
supported and isn’t committed to ship updates as part of any official .NET updates. It is built and maintained by Microsoft employees (**and** other contributors)

src/Extensions/DataGrid.ODataAdapter/ODataAdapterServiceCollectionExtensions.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.ODataAdapter;
1+
// ------------------------------------------------------------------------
2+
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------------------
4+
25
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;
6+
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.ODataAdapter;
37

8+
#pragma warning disable IDE0130 // Namespace does not match folder structure
49
namespace Microsoft.Extensions.DependencyInjection;
10+
#pragma warning restore IDE0130 // Namespace does not match folder structure
511

612
/// <summary>
713
/// Provides extension methods to configure <see cref="IAsyncQueryExecutor"/> on a <see cref="IServiceCollection"/>.

src/Extensions/DataGrid.ODataAdapter/ODataAsyncQueryExecutor.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1-
using Microsoft.OData.Client;
1+
// ------------------------------------------------------------------------
2+
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------------------
4+
25
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;
6+
using Microsoft.OData.Client;
37

48
namespace Microsoft.FluentUI.AspNetCore.Components.DataGrid.ODataAdapter;
59

10+
/// <summary>
11+
/// An <see cref="IAsyncQueryExecutor"/> implementation for Microsoft.OData.Client.
12+
/// </summary>
613
internal class ODataAsyncQueryExecutor : IAsyncQueryExecutor
714
{
15+
/// <inheritdoc />
816
public bool IsSupported<T>(IQueryable<T> queryable) => queryable.Provider is DataServiceQueryProvider;
917

18+
/// <inheritdoc />
1019
public async Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken)
1120
=> (int)(await ExecuteAsync(((DataServiceQuery<T>)queryable.Take(0)).IncludeCount(), cancellationToken)).Count;
1221

22+
/// <inheritdoc />
1323
public async Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken)
1424
=> [.. await ExecuteAsync(queryable, cancellationToken)];
1525

0 commit comments

Comments
 (0)