DelegateDecompiler icon indicating copy to clipboard operation
DelegateDecompiler copied to clipboard

DecompileAsync() with ToDictionaryAsync() doesn't seem to work?

Open JohanHeyvaert opened this issue 1 year ago • 1 comments

Hello there,

We are upgrading (or should I say rewriting) our application from .NET 4.8 + EF6 to .NET 8 + EF Core. We are using the latest version of DelegateDecompiler.EntityFrameworkCore5 (0.34.0). Almost all queries are working perfectly, except those where we use ToDictionaryAsync().

For example:

var test = await DbContext.Tests
      .Where(x => !x.IsDeleted) // a computed property
      .Where(x => !x.Organization.IsDeleted) // another computed property
      .GroupBy(x => x.Test.Organization)
      .Select(requests => new
      {
        OrganizationLabel = requests.Key.DisplayName, // Computed property
        Count = requests.Count()
      })
      .OrderByDescending(y => y.Count)
      .Take(20)
      .DecompileAsync()
      .ToDictionaryAsync(x => x.OrganizationLabel, x => x.Count);

When running this code, it errors out with:

The LINQ expression 'x => x.CultureCode == __CurrentThread_CurrentUICulture_TwoLetterISOLanguageName_0' 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'.

It refers to the code behind the computed property OrganizationLabel, where we retrieve the organization name in the current user's language. For this we use an extension method:

public class Organization
{
//................
    [Computed]
    public string Name => Names.Translate();
//...............
}
public static class TranslationExtensions
{
  [Computed]
  public static string Translate(this IEnumerable<Translation> translations)
  {
    return translations.Translate(Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName);
  }
  [Computed]
  public static string Translate(this IEnumerable<Translation> translations, string languageCode)
  {
    return translations.GetTranslation(languageCode)?.Content;
  }
  [Computed]
  public static Translation GetTranslation(this IEnumerable<Translation> translations, string languageCode)
  {
    return translations.First(x => x.CultureCode == languageCode);
  }
}

This works in other queries without a problem. For this query I've also tried to simplify and inline the expressions while adding the .Computed() method. But again the same error.

Is DecompileAsync() with ToDictionaryAsync() is supposed to work or do we need to use another approach?

Thanks for your advice!

JohanHeyvaert avatar Nov 20 '24 09:11 JohanHeyvaert

Can you try manually expand the query and test if it works?

hazzik avatar Mar 01 '25 02:03 hazzik