1

Using System.Linq.Dynamic.Core.

I have the following code on a Blazor component:

    private void TestFunc()
    {
        List<DataRow> dataRows = new List<DataRow>()
        {
            new DataRow("Australia", "NSW", "a", 10),
            new DataRow("Australia", "NSW", "b", 20),
            new DataRow("Australia", "VIC", "no", 10),
            new DataRow("New Zealand", "AUK", "no", 25),
            new DataRow("New Zealand", "AUK", "no", 15)
        };
        List<string> groupByFields = new List<string>() { "FieldA" }; // Test variable. This will not be defined at compile-time
        string aggregatorField = "MeasureA";
        string aggregatorFunction = "Sum";

        var groupings = dataRows.AsQueryable().GroupBy($"new ({string.Join(",", groupByFields)})");
        var aggregatedGroups = groupings.Select($"new (Key, {aggregatorFunction}({aggregatorField}) AS Value)").ToDynamicArray();

        Console.WriteLine(aggregatedGroups.Length);

        // This is the line that throws
        aggregatedGroups.ToList().ForEach(x => Console.WriteLine(x));
    }

    public record DataRow(string FieldA, string FieldB, string FieldC, double MeasureA);

    protected override void OnInitialized()
    {
        base.OnInitialized();

        TestFunc();
    }

But when I try and render the component, get the following error:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Operation is not valid due to the current state of the object.
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Reflection.Emit.GenericTypeParameterBuilder.GetGenericParameterConstraints()
   at Microsoft.CSharp.RuntimeBinder.SymbolTable.AddAggregateToSymbolTable(NamespaceOrAggregateSymbol parent, Type type)
   at Microsoft.CSharp.RuntimeBinder.SymbolTable.LoadSymbolsFromType(Type type)
   at Microsoft.CSharp.RuntimeBinder.SymbolTable.GetCTypeFromType(Type type)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetArgumentType(ICSharpBinder p, CSharpArgumentInfo argInfo, Expression param, DynamicMetaObject arg, Int32 index)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.CreateArgumentArray(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
   at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
   at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(ICSharpBinder action, RuntimeBinder binder, DynamicMetaObject[] args, IEnumerable`1 arginfos, DynamicMetaObject onBindingError)
   at Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder.FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
   at System.Dynamic.InvokeMemberBinder.FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args)
   at System.Dynamic.DynamicMetaObject.BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
   at System.Dynamic.InvokeMemberBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
   at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
   at System.Runtime.CompilerServices.CallSiteBinder.BindCore[Action`3](CallSite`1 site, Object[] args)
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[Type,Object](CallSite site, Type arg0, Object arg1)
   at StockAnalysis.WebAssembly.Pages.Index.<>c.<TestFunc>b__4_0(Object x) in C:\Users\Harry\source\repos\StockAnalysis\StockAnalysis.WebAssembly\Pages\Index.razor:line 75
   at System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ForEach(Action`1 action)
   at StockAnalysis.WebAssembly.Pages.Index.TestFunc() in C:\Users\Harry\source\repos\StockAnalysis\StockAnalysis.WebAssembly\Pages\Index.razor:line 75
   at StockAnalysis.WebAssembly.Pages.Index.OnInitialized() in C:\Users\Harry\source\repos\StockAnalysis\StockAnalysis.WebAssembly\Pages\Index.razor:line 84
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

Interstingly, the console app yields the length of aggregatedGroups to be of length 2, whereas in web assembly, it is of length 1.

The code works perfectly fine in a console app which is strange (even with the same System.Linq.Dynamic.Core version == 1.2.12). I honestly don't know what to do. Any help would be greatly appreciated, thanks!

Harry Stuart
  • 1,781
  • 2
  • 24
  • 39
  • A web connection you are using GUEST account that doesn't have the same privileges as a user account. The data is located at following : C:\Users\Harry\source\repos\StockAnalysis\StockAnalysis.WebAssembly\Pages\Index.razor:line 78. You do not have access to the folder c:\Users\Harry. You can put data in a folder that can be reached by the web connection. – jdweng Aug 07 '21 at 15:23
  • 1
    That is not even [misinformation](https://meta.stackoverflow.com/q/392514/11683) @jdweng, that is some next level BS. – GSerg Aug 07 '21 at 15:34
  • Are you sure the *same exact* code runs fine in console? Does the console code have the same definition for `DataRow`? – GSerg Aug 07 '21 at 15:49
  • Yes, it’s a literal copy and paste using linq dynamic core package version 1.2.12 – Harry Stuart Aug 07 '21 at 15:51
  • Does it change anything if you dumb down the `record` to `class`? Also please annotate which lines in this listing are 75 and 78. – GSerg Aug 07 '21 at 15:53
  • I'm afraid we'll have to see the TESTBULLSHIT to analyse the problem. – H H Aug 07 '21 at 16:07
  • hahaha, you can see my frustration with trying to solve this. I renames the function `Func` for the post – Harry Stuart Aug 07 '21 at 16:08
  • Dumbing down to a `class` does not work. – Harry Stuart Aug 07 '21 at 16:14
  • Why would you want to use System.Linq.Dynamic? I guess it's not supported on WebAssembly and you could live without the bloat if it is. Your DataRow is type-safe, dynamic can only invite SQL inection. – H H Aug 07 '21 at 16:16
  • So long story short, I have a list of data rows and need to `GroupBy` a list of keys. However, I do not know this list of keys at compile time, rather it is fed to the Blazor component at runtime (depends on user interaction). So I needed a way of calling `GroupBy` with a yet-to-be-known list of keys. Does that make sense? – Harry Stuart Aug 07 '21 at 16:18
  • Also, why in OnAfterRender ? This code looks like it belongs in OnInitialzied. – H H Aug 07 '21 at 16:18
  • Thie above snippet is purely for testing purposes, that is why it looks out of place. OnAfterRender or OnInitialised, I've got it there simply to try and test the code, it won't live there. TO clarify my above comment, although the data row is type safe, the list of `GroupBy` keys may be shorter than the number of record fields, and may be in a different order so I need to tackle it dynamically. Basically, group the data rows by some ordered subset of its fields. – Harry Stuart Aug 07 '21 at 16:20
  • I'm reasonably sure this is [caused](https://stackoverflow.com/a/30118465/11683) by the `y => properties.First(z => z.Name == y)`, but it would still be better if you [annotated](https://stackoverflow.com/questions/68693647/linq-expression-throwing-an-error-in-blazor-but-not-console-app#comment121399586_68693647) the line numbers. – GSerg Aug 07 '21 at 16:21
  • So Linq GroupBy with variable keys might have been a better question. – H H Aug 07 '21 at 16:21
  • 1
    Well, the above code is the supposed answer to that question, and I assure you that it works perfectly in my console app. So the question at hand is why it isn't working in web assembly – Harry Stuart Aug 07 '21 at 16:23
  • So I've just checked, and I've updated my question to show the refined error. – Harry Stuart Aug 07 '21 at 16:25
  • Check out https://stackoverflow.com/a/33286787/60761 , maybe that resolves the issue in cleaner way. – H H Aug 07 '21 at 16:43
  • Thanks, I'll have a look. Also, I updated the question as I managed to narrow it down a bit further. Seems like the groupby method is behaving differently in web assembly, idk why – Harry Stuart Aug 07 '21 at 16:45
  • Using the dynamic linq library for this may be obscure, but it works perfectly in a console app and to me, seems rather elegant. Pity I can't get it to work in web assembly – Harry Stuart Aug 07 '21 at 16:47
  • Please double check that the webpage is not running stale code, and dump the entire `dataRows` on the page unprocessed. What's the child count of the only member of `aggregatedGroups`? – GSerg Aug 07 '21 at 17:59
  • Since it's about rendering you should look at what `Console.WriteLine(x)` does in webassembly when processing the result of `ToDynamicArray()`. – Gert Arnold Aug 07 '21 at 20:29

0 Answers0