Filtering Grid with UrlAdaptor on complex Objects generates LINQ Error

Hello,

I'm implementing a fully dynamic grid system on my project, with UrlAdaptor.
Actually I encountered a problem with backEnd filtering IQueryable DataSource with complex Object data field on grid columns.
(PS. The filtering works well with NON complex object/NON navigations columns.)

Ex. Error 
(Complex Object / Navigation)

<e-grid-column field="Task.Title" type="string" headerText="TASK" width="" textAlign="Left"></e-grid-column>

From Method: 
public IQueryable<T> PerformFilteringSyncfusion<T> (IQueryable<T> dataSource, DataManagerRequest dm) where T : class

        {

            DataOperations operation = new DataOperations();

            if (dm.Where != null && dm.Where.Count > 0) //Filter

                dataSource = operation.PerformFiltering(dataSource, dm.Where, dm.Where[0].Operator);


            return dataSource;

        }


Generates this error: 
The LINQ expression 'DbSet<Report>()

    .Where(r => r.IsDeleted == False && r.DateStart.Month == DateTime.Now.Month)

    .OrderBy(r => r.DateStart)

    .Join(

        inner: DbSet<Task>(),

        outerKeySelector: r => EF.Property<Guid?>(r, "IdTask"),

        innerKeySelector: t => EF.Property<Guid?>(t, "Id"),

        resultSelector: (o, i) => new TransparentIdentifier<Report, Task>(

            Outer = o,

            Inner = i

        ))

    .Where(r => r.Inner == null ? null : new TaskDTO{

        Title = r.Inner.Title,

        Description = r.Inner.Description,

        IsDefault = r.Inner.IsDefault,

        IsDisabled = r.Inner.IsDisabled,

        Reports = null,

        ProductionOrderTasks = null,

        Id = r.Inner.Id,

        DateCreated = (DateTime?)r.Inner.DateCreated,

        DateUpdated = r.Inner.DateUpdated,

        IsDeleted = r.Inner.IsDeleted

    }

     != null && (r.Inner.Title ?? "").ToLower().StartsWith("a"))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Can you help me resolve this issue?

Thanks in advice, best regards.


5 Replies 1 reply marked as answer

JC Joseph Christ Nithin Issack Syncfusion Team February 26, 2024 07:07 PM UTC

Hi Martino,


Greetings from Syncfusion support.


  Before proceeding with your solution, we would like you to share the below details.


  • Complete grid rendering code.
  • Details of the model class code.
  • Video demo of the issue you are facing.
  • Simple sample to reproduce the issue you are facing.
  • Syncfusion package version.


Regards,

Joseph I.



NO notMartino February 27, 2024 09:57 PM UTC

Hello Joseph,


Thanks for the response, below the requested details:

  • Grid (tried both, with/without expand query command)
    <div class="col-12">
        <ejs-grid id="grid-user" allowPaging="true" allowSorting="true" allowFiltering="true" allowResizing="true" allowExcelExport="true" enableAltRow="true" locale="it-IT" allowReordering="false" query="new ej.data.Query().expand('Task')">

            <e-data-manager url="/Reports/Load" adaptor="UrlAdaptor"></e-data-manager>
            <e-grid-pagesettings pageSize="12"></e-grid-pagesettings>
            <e-grid-filterSettings type="Menu" mode="OnEnter"></e-grid-filterSettings>

            <e-grid-columns>
                <e-grid-column field="Id" headerText="ID" textAlign="Left" visible="false"></e-grid-column>

                @* <e-grid-column field="ProductionOrder.Code" type="string" headerText="COMMESSA" width="" textAlign="Left"></e-grid-column> *@
                <e-grid-column field="Task.Title" type="string" headerText="TASK" width="" textAlign="Left"></e-grid-column>
                <e-grid-column field="HoursAmount" headerText="Ore" width="" textAlign="Left"></e-grid-column>
                <e-grid-column field="DateStart" headerText="DATA" width="" textAlign="Left" customFormat="@(new { type ="date", format="dd/MM/yyyy" })"></e-grid-column>
                @* <e-grid-column field="Description" headerText="DESCRIZIONE" width="" textAlign="Left"></e-grid-column> *@

                <e-grid-column headerText="" width="40" textAlign="Center" template="#templateBtns"></e-grid-column>
            </e-grid-columns>
        </ejs-grid>
    </div> 
@* BTNS *@
<script id="templateBtns" type="text/x-template">
    <button class="utility-button grid me-1" onclick="editReport(`${id}`)">
        <i class="fa-solid fa-pencil"></i>
    </button>


    <button class="utility-button grid" onclick="deleteReport(`${id}`)">
        <i class="fa-regular fa-trash-can"></i>
    </button>
</script>
  • Models (DTOs and EF Core entities have the same props./navigations, i won't write those to save some text space, they are mapped with Mapster as IQueryable with ProjectToType() method)
 public class ReportDTO : BaseDTO {
     public double HoursAmount { get; set; }
     public DateTime DateStart { get; set; }
     public DateTime DateEnd { get; set; }
     public string? Description { get; set; }

     #region Navigations
     public Guid IdUser { get; set; }
     public UserDTO User { get; set; }

     public Guid IdProductionOrder { get; set; }
     public ProductionOrderDTO ProductionOrder { get; set; }

     public Guid IdTask { get; set; }
     public TaskDTO Task { get; set; }
     #endregion
 }

public class BaseDTO {
        public Guid Id { get; set; }
        public string? UserCreate { get; set; }
        public DateTime? DateCreated { get; set; }
        public string? UserUpdate { get; set; }
        public DateTime? DateUpdated { get; set; }
        public bool IsDeleted { get; set; } = false;
}

// The tested navigation prop.

public class TaskDTO : BaseDTO {
    public string Title { get; set; }
    public string? Description { get; set; }
    public bool IsDefault { get; set; } = false;
    public bool IsDisabled { get; set; } = false;

    #region Navigations
    public List<ReportDTO> Reports { get; set; } = new List<ReportDTO>();
    public List<ProductionOrderTaskDTO> ProductionOrderTasks { get; set; } = [];
    #endregion
}
View: {grid} // reported up in this reply
Controller/Action (used to load, filter, sort etc.):

  public async Task<IActionResult> Load([FromBody] DataManagerRequest dm){
      try
      {
          IQueryable<ReportDTO> reports = await _reportService.GetAllQueryable(
                  filter: x => x.IsDeleted == false && x.DateStart.Month == DateTime.Now.Month,
                  orderBy: x => x.OrderBy(y => y.DateStart)
                  includes: new() { "Task", "ProductionOrder" } //(tried with/without including the navigation prop)
              );
// The GetAllQueryable return the mapped IQueryable from EF Core DBContext, for the entity, and works fine (all the DB records list in queryable form)

          int count = 0;
          var result = PerformAllActionsSyncfusion(reports, dm, out count);

          return dm.RequiresCounts ? Json(new { result, count = count }) : Json(result);
      }
      catch (Exception ex)
      {
          return StatusCode(500, ClientConstants.ERROR_INTERNAL_DEFAULT);
      }
  }
// In the "PerformAllActionsSyncfusion" method i perform all the sorting, filtering, paging action as you report in the documentation, with the same order and count, everything works fine excluding the filtering of complex objects, specifically the LINQ error reported appear here:

  public IQueryable<T> PerformFilteringSyncfusion<T> (IQueryable<T> dataSource, DataManagerRequest dm) where T : class {
            DataOperations operation = new DataOperations();

            if (dm.Where != null && dm.Where.Count > 0) //Filter
                dataSource = operation.PerformFiltering(dataSource, dm.Where, dm.Where[0].Operator);

            return dataSource;
        }

  • Package version (NUGET) -> Syncfusion.EJ2.AspNet.Core 24.2.7

Thanks in advance, best regards.


JC Joseph Christ Nithin Issack Syncfusion Team March 13, 2024 03:10 AM UTC

Hi Martino,


   On inspecting the details and the code example provided, we suspect that you are facing issue, when you are filtering the datasource with complex Object data field on grid columns and get and error with the LINQ query in the EF core. The issue you have mentioned above is related to EF Core which has already been discussed in the below stack overflow thread.


Stack overflow: https://stackoverflow.com/questions/68737681/the-linq-expression-could-not-be-translated-either-rewrite-the-query-in-a-form


If you still face the issue, kindly share an issue reproducing sample, which will be helpful for us to validate the issue.



NO notMartino April 27, 2024 02:29 PM UTC

Hi Joseph,

I've found the solution time ago, sorry for the late response.

As you're saying, LINQ was unable to translate the conversion between DTOs and EF objects.


Actually I do have to pass the DataManagerRequest to the Service and apply the filters/sortings etc. on the IQueryable, before performing the projection of the mapping from EF obj to DTOs.


Below an example:


public async Task<(IQueryable<BankDTO>, int)> GetAllQueryableForSyncfusion(DataManagerRequest dm, Expression<Func<Bank, bool>> filter = null, Func<IQueryable<Bank>, IOrderedQueryable<Bank>> orderBy = null, List<string> includes = null)

{
         try
{
                int count = 0;

                IQueryable<Bank> banks = await _unitOfWork.BankRepository.GetAllQueryable(filter, orderBy, includes);

                banks = PerformAllActionsSyncfusion(banks, dm, out count).AsQueryable();

                IQueryable<BankDTO> bankDTOs = banks.ProjectToType<BankDTO>(_mapper.Config);

                return (bankDTOs, count);
            }
            catch (Exception ex)
            {
                AddError(ex.Message);
                return (null, 0);
            }


Thanks for your help, best regards.


Marked as answer

JS Johnson Soundararajan S Syncfusion Team April 29, 2024 10:47 AM UTC

Hi notMartino,


We are happy to hear that you resolved the reported query.


Please get back to us if you need any other assistance.


Regards,

Johnson Soundararajan S


Loader.
Up arrow icon