0

I'm using the Generic Repository pattern on my project and I have the following method that retrieves data according to the parameters provided :

public virtual async Task<IReadOnlyCollection<TEntity>> GetAsync(
   Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
{
    IQueryable<TEntity> query = dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    if (orderBy != null)
    {
        query = orderBy(query);
    }

    return await query.ToListAsync();
    

And I'm trying to add another paramter to apply a DistinctBy filter and this's what I did :

public virtual async Task<IReadOnlyCollection<TEntity>> GetAsync(
   Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
   Expression<Func<TEntity, object>> distinctBy = null)
{
    IQueryable<TEntity> query = dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    if (orderBy != null)
    {
        query = orderBy(query);
    }

    if (distinctBy != null)
    {
        query = query.DistinctBy(distinctBy);
    }

    return await query.ToListAsync();
}

But it's not working and I dont understand what I'm doing wrong. Thsi gives me the following exception :

The LINQ expression 'DbSet...' 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'

Thank you.

Edit :

I created a new class in which i put the DistinctBy extension method I'm going to use :

public static class EntityFrameWorkExtensions
{
    public static IQueryable<TSource> DistinctByPlus<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
    {
        return source.GroupBy(keySelector)?.Select(x => x.FirstOrDefault());
    }
}

And on my GenericRepository class I edited the signature of my method and I used this new extension method like this :

 public virtual async Task<IReadOnlyCollection<TEntity>> GetAsync(
   Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
   Expression<Func<TEntity, object>> distinctBy = null)
{
    IQueryable<TEntity> query = dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    if (orderBy != null)
    {
        query = orderBy(query);
    }

    if (distinctBy != null)
    {
        query = query.DistinctByPlus(distinctBy);
    }
    
    int count = query.Count();
    return await query.ToListAsync();
}

Here's my call to this method :

var data = await _unitOfWork.UserRepository.GetAsync(x => x.userId == id, distinctBy: o => o.SupervisorId);

But now this's giving me another error :

Nullable object must have a value.

This exception is thrown exactly after int count = query.Count();. I know this line looks useless but I will need it later.

Even though none of my database table records have SupervisorId null and when I remove the distinctBy the call works perfectly.

Svyatoslav Danyliv
  • 13,476
  • 1
  • 9
  • 23
Veoxer
  • 13
  • 3
  • The error message is probably being honest, and the (new as of .NET6) method `DistinctBy` is not supported by the EF core driver trying to translate it into sql. You're probably best off trying one of the techniques described [here](https://stackoverflow.com/questions/32619338/ef-distinctby-on-an-iqueryable). – Kirk Woll Mar 21 '22 at 23:17
  • Oh didn't know that DistinctBy wasn't supported. Thanks man I'll go with GroupBy then. – Veoxer Mar 21 '22 at 23:26
  • @KirkWoll So I'm having a lot of troubles trying to use the extension method in my project. I edited my question can you please check it out. – Veoxer Mar 22 '22 at 00:32
  • Try to use the following [extension](https://stackoverflow.com/a/69100842/10646316). if it works without repository pattern, it can be easily adopted to use in your abstraction. – Svyatoslav Danyliv Mar 22 '22 at 04:53
  • The last query using your custom `DistinctByPlus` implementation (with correct signature `IQueryable` instead of just `IQueryable`) has nothing to do with your data, but simple current EF Core `Count()` query translation bug (because `ToList{Async>` works). – Ivan Stoev Mar 22 '22 at 07:49
  • @SvyatoslavDanyliv Your extension methid didn't work for some reason and it's giving me the following exception `The LINQ expression {...} could not be translated` even though my query is pretty simple and doesn't contain anything but the distinctby. – Veoxer Mar 22 '22 at 10:43
  • Your "simple" query is not so simple in terms of SQL. Does your `GroupBy` variant works? It should work only with EF Core 6. – Svyatoslav Danyliv Mar 22 '22 at 11:16
  • @SvyatoslavDanyliv I am using using EF Core 6 in my project, and I didn't understand what you meant by whether my `GroupBy` variant works or not. When I tried the code above in my question in which I implemented `DistinctByPlus` using `GroupBy` it didn't work too if that's what you're asking. – Veoxer Mar 22 '22 at 12:15

0 Answers0