0

I have the following code in my repository. For some reason, query.Include() method does not work and related entity isn't included in result. Double checked if the property name is correctly passed. Maybe I am using it in wrong way? Any Ideas?

public IEnumerable<TEntity> Get(
        Func<TEntity, bool> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> order = null,
        string includedProperties = null)
    {
        IQueryable<TEntity> query = _context.Set<TEntity>();

        if (filter is not null)
        {
            query = query.Where(filter).AsQueryable();
        }

        if (order is not null)
        {
            query = order(query);
        }

        if (includedProperties is not null)
        {
            var properties = includedProperties.Split(',', StringSplitOptions.RemoveEmptyEntries);

            foreach (var property in properties)
            {
                query.Include(property);
            }
        }

        return query;
    }
Nomag
  • 33
  • 1
  • 5
  • A general point for working with IQueryable - you likely want to use [Queryable.Where](https://learn.microsoft.com/en-us/dotnet/api/system.linq.queryable.where?view=net-6.0) rather than [Enumerable.Where](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where?view=net-6.0). That would mean you would change the type of `filter` to `Expression>`. See e.g. https://stackoverflow.com/questions/2876616/returning-ienumerablet-vs-iqueryablet. (This does not answer your question, but may be helpful in improving your code's performance.) – Andrew McClement Feb 26 '22 at 15:15
  • @AndrewMcClement thanks for a hint. Actually it resolves my problem. I don't know why yet, but calling Include() on after using AsQuerable() on IEnumerable does not work in this case. – Nomag Feb 26 '22 at 15:22
  • Now take a step back, and consider eliminating that useless code and have the callers compose IQueryables without shoving expressions and string arrays in to your repo method. – David Browne - Microsoft Feb 26 '22 at 15:44

2 Answers2

2

I think that you need to change to the following

query =query.Include(property);

Alen.Toma
  • 4,684
  • 2
  • 14
  • 31
  • It still isn't including related entity. – Nomag Feb 26 '22 at 14:49
  • Looks like you are right, but also query.Where(filter).AsQuerable() have influence on including. Calling Include before filtering resolved the problem. – Nomag Feb 26 '22 at 15:13
  • Actually, now I think about it, Enumerable.Where forces it to become two separate queries - whereas Queryable.Where would keep it as one query, and therefore query.Include would presumably still work where it is (i.e. your current order of operations would be fine) – Andrew McClement Feb 26 '22 at 15:20
1

Credit to @Alen.Toma for spotting the missing assignment in the original code.

In the original code, as soon as we use Enumerable.Where(...), the original query on the database can no longer be modified, since we have filtered the objects in C#. This means that query.Include acts on the result of Enumerable.Where, not on the the original db query, and therefore does not have the desired effect.

Full modified code:

public IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> order = null,
        string includedProperties = null)
    {
        IQueryable<TEntity> query = _context.Set<TEntity>();

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

        if (order is not null)
        {
            query = order(query);
        }

        if (includedProperties is not null)
        {
            var properties = includedProperties.Split(',', StringSplitOptions.RemoveEmptyEntries);

            foreach (var property in properties)
            {
                query = query.Include(property);
            }
        }

        return query;
    }
Andrew McClement
  • 1,171
  • 5
  • 14