1

Setup

  • Asp.Net Core 3.1
  • EF Core 3.1

I am writing a LINQ statement to retrieve some entities from DB and I encountered a problem. This is the statement:

var Tag = "this is an input parameter";
location.SRID = 4326;
var posts = await _context.Posts
    .Include(p => p.Location)
    .Include(p => p.Event)
    .Include(p => p.Repeatable)
    .Include(p => p.Voucher)
    .Include(p => p.Tags)
    .ThenInclude(pt => pt.Tag)
    .Where(p => p.ActiveFlag == 1 &&
           p.Location.Location.IsWithinDistance(location, radius * 1000) &&
           p.EventTime > today &&
           p.Tags.All(pt => pt.Tag.TagName.Contains(Tag.ToLower()))) // always true
    .AsNoTracking().ToListAsync();

The problem is that p.Tags.All(condition) returns true for all, always. Looks like it's ignoring this condition. I even tried using TrueForAll() instead, but that doesn't work at all with EF Core 3.1, it returns:

...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 either AsEnumerable()...

This is the shrunk Post model and its relationship with PostTags and Tags:

public class Post
{
    public int Id { get; set; }

    public virtual List<PostTags>? Tags { get; set; }
}

public class PostTags
{
    public virtual Tag Tag { get; set; }

    public int TagId { get; set; }

    public virtual Post Post { get; set; }

    public int PostId { get; set; }
}

public class Tag
{
    public int Id { get; set; }

    public string TagName { get; set; }

    public virtual IEnumerable<PostTags>? Posts { get; set; }
}
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Gicu Mironica
  • 585
  • 8
  • 22
  • 2
    Perhaps `Tag` contains an empty string? What value does `Tag` contain? I bet that if you try to put a constant there like `"randomstring"` the `All()` method won't return true. – devcrp Jul 01 '20 at 12:31
  • @devcrp I've just updated the post, that is an input parameter, I tried putting anything in it, still returns true – Gicu Mironica Jul 01 '20 at 12:33
  • 8
    `All` returns `true` if the collection is _empty_, I believe, so that might be something else to check. – Kirk Larkin Jul 01 '20 at 12:34
  • @KirkLarkin Yes, that solved the problem, thanks!! – Gicu Mironica Jul 01 '20 at 12:45
  • 1
    You're welcome. [This](https://stackoverflow.com/questions/7884888/why-does-enumerable-all-return-true-for-an-empty-sequence) and it's linked dupe explain some of the reasoning a bit more, if you're interested. – Kirk Larkin Jul 01 '20 at 12:48
  • 1
    @KirkLarkin post that as an answer so OP can accept it. Nice find! – n8wrl Jul 01 '20 at 12:59
  • 1
    Two other thoughts/optimizations - I suggest setting another variable to Tag.ToLower() to reduce the number of times that happens, and perhaps AND-ing !p.Tags.IsEmpty() before your .All(...) – n8wrl Jul 01 '20 at 13:00

0 Answers0