ToDataSource throws exception using EF Core 3.0 with groups

9 posts, 0 answers
  1. محمد
    محمد avatar
    1 posts
    Member since:
    Dec 2014

    Posted 30 Oct 2019 Link to this post

    the exception is:

    "Processing of the LINQ expression 'GroupByShaperExpression:
    KeySelector: t.Year,
    ElementSelector:EntityShaperExpression:
        EntityType: ProjectBudget
        ValueBufferExpression:
            ProjectionBindingExpression: EmptyProjectionMember
        IsNullable: False
    ' by 'RelationalProjectionBindingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information."

     

    this happens when the DataSourceRequest contains Group, and the IQueriable items are empty

     
  2. Aleksandar
    Admin
    Aleksandar avatar
    241 posts

    Posted 04 Nov 2019 Link to this post

    Hello,

    Thank you for reporting this issue. Based on the provided information, however, I was not able to reproduce the error reported. Would it be possible to modify the attached sample solution, so the issue is reproducible, or send a runable example, where the behavior is isolated? This way I could investigate the issue further?

    Looking forward to your reply.

    Regards,
    Aleksandar
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Ivan Zatko
    Ivan  Zatko avatar
    1 posts
    Member since:
    Jan 2019

    Posted 04 Dec 2019 Link to this post

    Same issue here ToDataSource with group is not working in EF Core 3.1
  4. Aleksandar
    Admin
    Aleksandar avatar
    241 posts

    Posted 06 Dec 2019 Link to this post

    Hello Ivan,

    The behavior can be related to a limitation in the EntityFramework version as suggested in the exception message. You could find details on Microsoft's documentation:

    The issue occurs upon query execution that is not supported by the database. EF Core 2 used client-side evaluations, but with EF Core 3 they are no longer supported. Groping with Entity Framework Core 3.0 is discussed further in this GitHub issue:

    Having said that to resolve the issue you could try calling ToList on the items collection before calling ToDataSourceResult and see how that affects the behavior. Alternatively, you could refactor the query generation to meet the Entity Framework Core 3.0 requirements.

    Regards,
    Aleksandar
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  5. Heiko
    Heiko avatar
    60 posts
    Member since:
    Nov 2018

    Posted 12 Mar 2020 in reply to Aleksandar Link to this post

    I found this thread because I have a similar problem using WPF and QueryableCollectionView. I clearly see the responsibility on the side of Telerik!! It seems that the way Telerik developers are building queries does not take into account how the query evaluation has changed in EF Core 3.x.

    See also this other thread of mine: https://www.telerik.com/forums/queryablecollectionview-and-ef-core-3-x

  6. Aleksandar
    Admin
    Aleksandar avatar
    241 posts

    Posted 17 Mar 2020 Link to this post

    Hello Heiko,

    The DataSourceResult uses LINQ internally. The valuation of expressions has been changed with the introduction of EF Core 3.x. The Kendo UI library is dependent on a lot of built-in functionalities that come with the ASP.NET Core framework. 

    The handling of the groups in the EF Core has been vastly commented in the GitHub repository below, owned by the creators of EF Core. More information on what are the changes introduced with the newer version and the impact on the data processing could be found in the issue below:

    https://github.com/dotnet/efcore/issues/17068

    Discussion on the GroupBy functionality has been moved to the following item:

    https://github.com/dotnet/efcore/issues/17653

    As you can see, the required is yet not supported in EF Core 3. That is why the ToList() workaround is still a valid option. Indeed, for large data sets, it is not a high-performance approach. In such scenarios creating a custom implementation for fetching the data, where only the relevant data is requested and grouped could be an alternative approach.

    Regards,
    Aleksandar
    Progress Telerik

    Get quickly onboarded and successful with Telerik UI for ASP.NET Core with the dedicated Virtual Classroom technical training, available to all active customers.
  7. Heiko
    Heiko avatar
    60 posts
    Member since:
    Nov 2018

    Posted 18 Mar 2020 in reply to Aleksandar Link to this post

    Hello Aleksandar!

    I cannot follow the argument "not yet supported in EF Core 3" and I can't see that in the discussion on github either. As far as I can see this will never be supported, simply because the underlying mechanisms how EF Core works have fundamentally changed. Maybe I have missed it, but there is no mentioning that for example grouping will move back to client side.

    For years DataSourceResult is the heart of everything working with ASP.NET and EF Core (and QueryableCollectionView on WPF side also). Paging, sorting, grouping, filtering is done through these classes. Of course I can do it myself, but then why should I spent money on a tool? To work around a bug that will remain in the long run because the cause is not fixed does not make sense.

    Regards
    Heiko

  8. Sanat
    Sanat avatar
    1 posts
    Member since:
    Jul 2019

    Posted 19 Mar 2020 in reply to Aleksandar Link to this post

    Hello Aleksandar,

     

    As a workaround,

    Is it supported by Telerik to use Sorting, filtering, Paging on IQuerable datasource, obtain DataSourceResult and rerun ToDataSourceResult with grouping request?

     using (var db = new BloggingContext())
                    {
                        IQueryable<Blog> blogs = db.Blogs.AsQueryable();
                        Debug.Assert(blogs.Count() > 0);

                        DataSourceRequest sortFilterPageRequest = prepareSortFilterPageRequest();
                        DataSourceResult sortFilterPageResult = blogs.ToDataSourceResult(sortFilterPageRequest);
                                            
                        var matchingBlogs = sortFilterPageResult.Data.OfType<Blog>();

                        DataSourceRequest groupingRequest = prepareGroupingRequest();
                        DataSourceResult finalResult = matchingBlogs.ToDataSourceResult(groupingRequest);

                        Console.WriteLine($"Total blogs in database:{blogs.Count()}");                    
                    }

     

    Thanks,

    Maulik.

  9. Aleksandar
    Admin
    Aleksandar avatar
    241 posts

    Posted 23 Mar 2020 Link to this post

    Hello Sanat,

    The ToDataSourceResult() method has several overloads and basically requires an IQueriable or an IEnumerable as a source of data and a DataSourceRequest object, so that filtering, sorting, paging and grouping are applied. The DataSourceRequest type has the following properties:

    public class DataSourceRequest
    {
        public DataSourceRequest();
     
        public int Page { get; set; }
        public int PageSize { get; set; }
        public IList<SortDescriptor> Sorts { get; set; }
        public IList<IFilterDescriptor> Filters { get; set; }
        public IList<GroupDescriptor> Groups { get; set; }
        public IList<AggregateDescriptor> Aggregates { get; set; }
    }

    Having said that, for scenarios where a query cannot be evaluated on the client-side and an exception is thrown you could implement custom Ajax binding where sorting, filtering and paging are performed on an IQuerable object, data is then materialized and grouping is performed on the materialized data. This data object could be passed as the Data property of a DataSourceResult object, that is returned to the View.

    public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request)
    {
        // Get the data (code omitted).
        IQueryable<Order> orders = new NorthwindEntities().Orders;
        // Apply filtering (code omitted).
        // Apply sorting (code omitted).
        // Apply paging (code omitted).
        // Materialize the IQueriable object and apply grouping
        // Initialize the DataSourceResult.
        var result = new DataSourceResult()
        {
            Data = orders, // Process data (paging and sorting applied).
            Total = total // The total number of records.
        };

    return Json(result); }

    For an example on implementing Custom Ajax Binding refer to the tab CustomAjaxBindingController.cs on the following link:

    https://demos.telerik.com/aspnet-mvc/grid/customajaxbinding

    Additional details on Custom Ajax Databinding could be found here.

    Regards,
    Aleksandar
    Progress Telerik

    Get quickly onboarded and successful with Telerik UI for ASP.NET Core with the dedicated Virtual Classroom technical training, available to all active customers.
Back to Top