简体   繁体   中英

query multi-level entity with filter at the lowest level

So I have 3 entity classes:

public partial class Event
{
    public Event()
    {
        Recurrences = new HashSet<Recurrence>();
    }
    public int Id { get; set; }
    public ICollection<Recurrence> Recurrences { get; set; }
}

public partial class Recurrence
{
    public Recurrence()
    {
        AspNetUsers = new HashSet<AspNetUser>();
    }
    public int Id { get; set; }
    public int EventId { get; set; }
    public ICollection<AspNetUser> AspNetUsers { get; set; }
}

public partial class AspNetUser
{
    public AspNetUser()
    {
        Recurrences = new HashSet<Recurrence>();
    }
    public string Id { get; set; }
    public string UserName { get; set; }
    public ICollection<Recurrence> Recurrences { get; set; }
}

I would like to get the event given the aspnetuser.id using line to entity. so far this is what I have but it's returning an error:

// GET: api/Events?userId={userId}
    public IQueryable<Event> GetEvents(string userId)
    {
        return db.Events
             .Include(e => e.Recurrences
                .Select(u => u.AspNetUsers.Where(i => i.Id == userId)));
    }

When I exclude the where clause it works fine. Please help. Thanks in advance!

I don't think Include() means what you think it means. ( https://msdn.microsoft.com/en-us/library/bb738708%28v=vs.110%29.aspx ) What it does is tell the db set to be sure to bring in relationships for that object. By default (last I checked), the db context will auto pull in all relationships, so this isn't necessary. However, if you've turned off the lazy-loading ( http://www.entityframeworktutorial.net/EntityFramework4.3/lazy-loading-with-dbcontext.aspx ) then you'll need to .Include() all the relationships you want to have in the query.

This should solve your problem. I don't guarantee the SQL generated won't be silly, though.

If you have lazy-loading turned on:

db.Events.Include("Recurrences").Include("Recurrences.AspNetUsers")
  .Where(e => e.Recurrences
    .Any(r => r.AspNetUsers
      .Any(u => u.Id ==userId)));

If you have lazy-loading turned off:

db.Events
  .Where(e => e.Recurrences
    .Any(r => r.AspNetUsers
      .Any(u => u.Id ==userId)));

Also, if you have trouble seeing errors, you can .ToList() the query before returning so that it fails in your code and not deep inside the Web API stack. Personally, I like to do this so that I can try/catch the query and handle it properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM