blankface
blankface

Reputation: 6347

EF Core “InvalidOperationException: Include has been used on non entity queryable” on IQueryable

I have the following schema:

public class Post {
    public string Id {get;set;}
    public string Content {get;set;}
    public AppUser AppUser {get;set;}
    public List<PostTag> PostTags {get;set;}
}

public class Tag {
    public string Id {get;set;}
    public string Name {get;set;}
    public List<PostTag> PostTags {get;set;}
}

public class PostTag
{
    public string PostId { get; set; }
    public Post Post { get; set; }

    public string TagId { get; set; }
    public Tag Tag { get; set; }
}

With the following db relationships:

builder.Entity<PostTag>()
    .HasKey(x => new { x.PostId, x.TagId });

builder.Entity<PostTag>()
    .HasOne(st => st.Post)
    .WithMany(s => s.PostTags)
    .HasForeignKey(st => st.PostId);

builder.Entity<PostTag>()
    .HasOne(st => st.Tag)
    .WithMany(s => s.PostTags)
    .HasForeignKey(st => st.TagId);

I'm writing a query to get all the Posts that are linked to a specific Tag, based on the provided TagId.

First I get all the posts using:

var postsQuery = _ctx.PostTag
                    .Include(st => st.Post)
                    .Where(st => st.TagId == {provided TagId})
                    .Select(st => st.Post);

Since I want to include some further data to each post, I do:

var postsWithExtraData = postsQuery
                            .Include(s => s.AppUser)
                            .Include(s => s.PostTags)
                            .ThenInclude(st => st.Tag)
                            .OrderByDescending(s => s.TotalVoteCount)
                            .ToListAsync();

But the query breaks on the first .Include with this error:

EF Core “InvalidOperationException: Include has been used on non entity queryable”

Why is this happening and how can I fix it?

EDIT: Potential solution that I got to work:

var posts = _ctx.PostTag
                    .Include(st => st.Post)
                    .ThenInclude(s => s.AppUser)
                    .Include(st => st.Post)
                    .ThenInclude(s => s.PostTags)
                    .ThenInclude(st => st.Tag)
                    .Where(st => st.TagId == request.TagId)
                    .Select(st => st.Post)
                    .ToList();

Would love to know if this is a good approach or not.

Upvotes: 3

Views: 4825

Answers (2)

Karan
Karan

Reputation: 12619

If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.

So your code is giving error. You can do like below where you can use Includes in your first query and use OrderByDescending ToListAsync to next.

var postsQuery = _ctx.PostTag
                .Include(st => st.Post)
                    .ThenInclude(s => s.AppUser)
                .Include(st => st.Post)
                    .ThenInclude(s => s.PostTags)
                        .ThenInclude(st => st.Tag)
                .Where(st => st.TagId == {provided TagId})
                .Select(st => st.Post);
                
var postsWithExtraData = postsQuery                            
                        .OrderByDescending(s => s.TotalVoteCount)
                        .ToListAsync();

Upvotes: 4

Hesam Akbari
Hesam Akbari

Reputation: 1141

First, you should write Include and ThenInclude and then write your Condition

var postsWithExtraData = _ctx.PostTag
                            .Include(st => st.Post)
                            .Include(s => s.AppUser)
                            .Include(s => s.PostTags)
                            .ThenInclude(st => st.Tag)
                            .Where(st => st.TagId == {provided TagId})
                            .OrderByDescending(s => s.TotalVoteCount)
                            .ToListAsync();

Upvotes: 0

Related Questions