Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MudDataGrid: Add extensions method on IQueryable for easy filtering and ordering #8254

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

0xced
Copy link
Contributor

@0xced 0xced commented Feb 27, 2024

Description

This pull request introduces two new extensions methods on IQueryable: Where that takes a IEnumerable<IFilterDefinition<T>> and OrderBy that takes a IEnumerable<SortDefinition<T>>.

This enables a straightforward implementations of the ServerData function, for example with EF Core.

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace MudBlazor;

internal static class QueryGridExtensions
{
    public static async Task<GridData<T>> LoadServerDataAsync<T>(this IQueryable<T> source, GridState<T> state, CancellationToken cancellationToken = default)
    {
        var query = source.Where(state.FilterDefinitions).OrderBy(state.SortDefinitions);
        var items = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToListAsync(cancellationToken);
        var totalItems = await query.CountAsync(cancellationToken);
        return new GridData<T> { Items = items, TotalItems = totalItems };
    }
}

(A good implementation would need to order the source with a default ordering in case the sort definitions are empty.)

It also fixes #6682.

How Has This Been Tested?

Two new unit tests have been added: QueryFilterExtensionTest and QuerySortExtensionTest.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • The PR is submitted to the correct branch (dev).
  • My code follows the code style of this project.
  • I've added relevant tests.

@github-actions github-actions bot added enhancement New feature or request PR: needs review labels Feb 27, 2024
Copy link

codecov bot commented Feb 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.99%. Comparing base (345ec7c) to head (2c675f1).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #8254      +/-   ##
==========================================
+ Coverage   88.82%   88.99%   +0.17%     
==========================================
  Files         407      409       +2     
  Lines       12226    12252      +26     
  Branches     2441     2447       +6     
==========================================
+ Hits        10860    10904      +44     
+ Misses        834      819      -15     
+ Partials      532      529       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe NRT can be enable on this file? Like you did in QuerySortExtensions.cs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I did in in f60b021, rebased on the dev branch and force-pushed.

@Militancy
Copy link

Hey @0xced,

thanks for your pull request, I currently struggled to find a way to do those queries user friendly. For myself I would like that extension to be a bit more powerful.

Would you consider to implement an solution where its possible to query for included class structures, like for example extend the MemberExpression for each member of depth?

@vernou
Copy link
Contributor

vernou commented Feb 29, 2024

@Militancy

Would you consider to implement an solution where its possible to query for included class structures, like for example extend the MemberExpression for each member of depth?

I am not sure I understand...
Have you a example?
Will the resulting expressions be EF compatible?

@Militancy
Copy link

@vernou
In a specific example we have two classes, where we want to query for a value of a nested class. As i tested your stuff i noticed that the the extension for filtering was already working for nested class properties. Only on the sorting part a adjustment was necessary.

I tested it with my own class structures with EF on SQLite successfully.

Example Column for MudDataGrid
<PropertyColumn Property="p => p.B.Name"/>

Class example

public class A {
    public int BId { get; set; }
    public B { get; set; }
}

public class B {
    public string Name { get; set; }
}

A "solution" would be sth like this. But I dont know if its the best way to go.

MemberExpression propertyExpression;
if(sortDefinition.SortBy.Contains('.'))
{
    var properties = sortDefinition.SortBy.Split('.');
    propertyExpression = Expression.Property(parameter, properties.First());
    foreach(var prop in properties.Skip(1))
        propertyExpression = Expression.Property(propertyExpression, prop);
}
else
    propertyExpression = Expression.Property(parameter, sortDefinition.SortBy);

@ScarletKuro
Copy link
Member

ScarletKuro commented Feb 29, 2024

Hi, thanks for the PR.

@mikes-gh I think it's very problematic for us that this is not trim compatible because of this line

var propertyExpression = Expression.Property(parameter, sortDefinition.SortBy);

if SortDefinition contained the type information of the property it would be, since there is an overload that accepts type info.
Honestly, I'm not sure what to do with this PR, tho I like the idea.

I will @tjscience let to decide.

@0xced
Copy link
Contributor Author

0xced commented Mar 14, 2024

@Militancy I think I figured out a way to support your scenario. Instead of adding one extension method, I added two extension methods (and force pushed my branch). The new one that I added takes an additional Func<ParameterExpression, SortDefinition<T>, Expression> that lets you define the expression as you see fit for the given sort definition. The default implementation for the standard case does Expression.Property(parameter, sortDefinition.SortBy) but now you can write your own if that's not enough.

@ScarletKuro I don't think that's a problem since the type T is user supplied and thus very unlikely to be trimmed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request PR: needs review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DataGrid sorting support ef with DataGridExtensions.EFOrderBySortDefinitionsing
4 participants