iQuarc/DataLocalization

Implement IAsyncEnumerable<T>

Closed this issue · 5 comments

First of all, thank you, I like the way I can solve translations in my app and I really think that your library is very helpful.

And once said that I've found and issue and, well, this is a feature request.

The issue:
using .Localize(culture) extension with async queries throws Invalid Operation Exception due to ILocalizedQueryable is not implementing IAsyncEnumerable:

System.InvalidOperationException
HResult=0x80131509
Message=The source IQueryable doesn't implement IAsyncEnumerable. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.
Source=Microsoft.EntityFrameworkCore
StackTrace: (I'd say it is useless)

So, my original code without translations looked like this:

public async Task<ThingsListViewModel> Handle(GetThingsListQuery request, CancellationToken cancellationToken)
        {
            return new ThingsListViewModel
            {
                Things = await _context
                                        .Things
                                        .ProjectTo<ThingsLookupViewModel>(_mapper.ConfigurationProvider)
                                        .ToListAsync(cancellationToken)
            };
        }

Then I tried this:

public async Task<ThingsListViewModel> Handle(GetThingsListQuery request, CancellationToken cancellationToken)
        {
            return new ThingsListViewModel
            {
                Things = await _context
                                        .Things
                                        .ProjectTo<ThingsLookupViewModel>(_mapper.ConfigurationProvider)
                                        .Localize(culture)
                                        .ToListAsync(cancellationToken)
            };
        }

Having that exception at runtime :(... But fortunatelly, as expected, I manged to get my translated things like this:

public async Task<ThingsListViewModel> Handle(GetThingsListQuery request, CancellationToken cancellationToken)
        {
            CultureInfo culture = Thread.CurrentThread.CurrentCulture;


            return new ThingsListViewModel
            {
                Things = _context
                                        .Things
                                        .ProjectTo<ThingsLookupViewModel>(_mapper.ConfigurationProvider)
                                        .Localize(culture)
                                        .ToList()
            };
        }

Then I wonder if there is any chance to hace a LocalizeAsync(culture) in the short term.

Thanks in advance.

@JuanGarciaCarmona Thanks for the feedback. I will look into what needs to be done to support IAsyncEnumerable

I had not too much time but I passed thorugh the code and around 10 StackOVerflow threads and... I guess... I'd say... that my request is too complex to be accomplished by refactring or extending your library and that it would couple it to EntityFrameworkCore... Do you think I am right?

But, well, there is a workaround, and it is to wrap the _context query with a Task.FromResult() or, in my case, Task.Run() with the Cancellation Token so that I can keep that method async. I am hapy with this workaround but in some concrete cases I will preffer to code manually my projections (with some filters) than relying on Localize extension method.

Anyway, if you find out a way of working with EF Core async methods it would be an awesome improvement and I'll be glad to refactor all my code.

Thanks!

I've investigated what it takes to implement this and unfortunately, this is blocked by the current implementation of EF core async. Issue

Hmm, I totally understand that this would make the code having a tight coupling to EF Core.. but perhaps a solution would be to createa a iQuarc.DataLocalization.EFCore, in which it would be okey to have a tight coupling to EFCore. It might not be the perfect solution, but until the EFCore team and the .NET Core team comes up with a joint effort to make this possible it's the only solution I can see right now.

@MrRosendahl I'll investigate if that is possible. The problem wasn't tight coupling, but the fact that EF in its async methods calls internal methods on the provider. This localization mechanism wraps the provider, so naturally, those extension methods fail.