excelexport.net-6.0closedxmldynamic-linq

'Parameter count mismatch' Error when trying to insert List<dynamic> to Excel using closedXml InsertData


I am trying to export dynamic list items to excel using ClosedXML. The goal is to allow end user to select the columns to be exported. Since the columns are dynamic, I use.ToDynamicListAsync() of System.Linq.Dynamic.Core name space. The problem is excel export works fine if I create anonymous object but throws error when I directly pass the select query as shown below. I directly pass the select cols bcoz the cols will be known only at runtime.

Below is the code snapshot for clarity

            using ClosedXML.Excel;
            using System.Linq.Dynamic.Core;

            var filter = "MeetingNo = 85";
            var query = context.PrmProjects.AsNoTracking().Where(filter);

            var items = await query.Select(x => new
            {
                x.OrganizationId,
                x.ProjectNo,
                x.MeetingNo,
                x.Name
            }).ToDynamicListAsync();
            using var wb = new XLWorkbook();
            var ws = wb.Worksheets.Add();
            ws.Cell(3, 1).InsertData(items); /// WORKS FINE


            var selectQuery = $"new(OrganizationId,ProjectNo,MeetingNo,Name)";
            var items1 = await query.Select(selectQuery).ToDynamicListAsync();
            using var wb2 = new XLWorkbook();
            var ws2 = wb2.Worksheets.Add();
            ws2.Cell(3, 1).InsertData(items1); /// THROW ERROR 'Parameter count mismatch' 

`

In the above sample code InsertData with the list 'items' works fine but 'items1' throws an error 'Parameter count mismatch'

Screenshot of List 'items', working fine: enter image description here

Screenshot of List 'items1', throw error:enter image description here

Error screenshot: enter image description here

Can any one please help me. What am I doing wrong.


Solution

  • The cause for this error is that System.Linq.Dynamic.Core creates a new dynamic type based on DynamicClass which does also have an indexer:

    public object? this[string name]
    {
        get
        {
            //
        }
    
        set
        {
            //
        }
    }
    

    The ClosedXml calls GetProperties(...) in the ObjectReader.cs class and this GetProperties does return 5 entries:

    So actually ClosedXML should be fixed to exclude indexer methods. Example:

    int parameters = propertyInfo.GetIndexParameters().Length;
    if (parameters > 0)
    {
        // The property is an indexer, skip this.
        continue;
    }