Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Includes doesn't work with LinqKit AsExpandable

I'm trying to use LinqKit AsExpandable in my EfCore2.0 project and I am running into this problem where the Includes doesn't work.

In attempting to debug this I have downloaded the LinqKit source from github and have replaced the Nuget references in my project with Project references.

When debugging with the LinqKit project, I noticed that the my call to Include wasn't hitting a breakpoint I set on ExpandableQueryOfClass<T>.Include.

I did some further testing and noticed the breakpoint is hit if I first cast to ExpandableQueryOfClass (this is an internal class in LinqKit which I made public, so I can't do the cast if I'm referencing the Nuget package).

Is this a bug in LinqKit or am I doing something wrong?

Here is my test code.

using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

using Internal.DAL.Db;
using Internal.Models.Customer;

using LinqKit; // Referencing LinqKit.Microsoft.EntityFrameworkCore
using Xunit;

namespace Internal.EntityFramework.Tests
{
    public class UnitTest1
    {
        private DbContextOptionsBuilder<DataContext> _ctxBuilder =>
            new DbContextOptionsBuilder<DataContext>().UseSqlServer(Connection.String);

        [Fact]
        public async Task SuccessTest()
        {
            using (var ctx = new DataContext(_ctxBuilder.Options))
            {
                var query = 
                    (
                        // this cast is the only difference between the methods
                        (ExpandableQueryOfClass<Order>)
                        ctx.Orders
                        .AsExpandable()
                    )
                    .Include(r => r.Customer)
                    .Take(500);

                var responses = await query.ToListAsync();

                // this succeeds
                Assert.All(responses, r => Assert.NotNull(r.Customer));
            }
        }

        [Fact]
        public async Task FailTest()
        {
            using (var ctx = new DataContext(_ctxBuilder.Options))
            {
                var query = ctx.Orders
                    .AsExpandable()
                    .Include(r => r.Customer)
                    .Take(500);

                var responses = await query.ToListAsync();

                // this fails
                Assert.All(responses, r => Assert.NotNull(r.Customer));
            }
        }
    }
}

Edit 2018-05-15: There is an open issue on the LinqKit github repository.

like image 615
jag Avatar asked Mar 07 '23 23:03

jag


1 Answers

I'm not sure whether this is LINQKit or EF Core fault (definitely it's not yours).

For sure it's caused by the EF Core Include / ThenInclude implementations which all include a check for source.Provider is EntityQueryProvider and do nothing in case it's false.

I'm not sure what's the idea of EF Core designers - probably custom query providers to inherit from EntityQueryProvider, but at the same time the class is part of the infrastructure and marked as not supposed to be used.

I also have no idea how LINQKit is planning to address it, but as you noticed the current implementation definitely is broken/not working. At the moment it looks to me more like a WIP.

The only workaround I see at this time is to apply AsExpandable() after includes.

like image 156
Ivan Stoev Avatar answered Apr 27 '23 06:04

Ivan Stoev