简体   繁体   English

实体框架 - 如何过滤渴望加载的导航/关系属性?

[英]Entity framework - how to filter eager loaded navigational/relational properties?

I have the following Entity Framework 4.1 entities and relationships 我有以下Entity Framework 4.1实体和关系

Concert ConcertId, AdministratorUserId, Name, IsDeleted Concert ConcertId,AdministratorUserId,Name,IsDeleted

Booking BookingId, ConcertId, UserId, IsDeleted 预订 BookingId,ConcertId,UserId,IsDeleted

UserId , UserId, Name, IsDeleted UserId ,UserId,Name,IsDeleted

Relationships Concert 1.....M Booking 1....1 User 关系音乐会1 ..... M预订1 .... 1位用户

Now I am trying to select all the Concerts for a particular AdminstratorUserId but also include all the Bookings for each Concert and also the User details for each booking. 现在我正在尝试为特定的AdminstratorUserId选择所有音乐会,但也包括每个音乐会的所有预订以及每个预订的用户详细信息。 I would also like to apply a filter where IsDeleted == false for each Concert, Booking and User. 我还想为每个音乐会,预订和用户应用IsDeleted == false的过滤器。 I Would like to return a List of Concerts which have their Booking and User details maintained as navigational properties. 我想返回一份音乐会列表,其中的预订和用户详细信息保留为导航属性。

In SQL, this is what I am trying to achieve: 在SQL中,这是我想要实现的:

SELECT *
FROM concert c, booking b, user u
WHERE c.ConcertId = b.ConcertId AND b.UserId = u.UserId AND c.AdministratorId = 10
AND c.IsDeleted = false AND b.IsDeleted = false AND u.IsDeleted = false

As far as I am aware, using the "Include" method to eager load, doesn't allow filtering or subqueries of the child entity it loads in; 据我所知,使用“Include”方法进行预加载,不允许对其加载的子实体进行过滤或子查询; it returns all records for that join, so I tried to use an anonymous projection as follows: 它返回该连接的所有记录,因此我尝试使用匿名投影,如下所示:

int adminId = 10;

var concerts = _context.Concerts
    .Where(p => p.AdministratorId == adminId && p.IsDeleted == false)
    .Select(p => new {
        Concerts = p,
        Bookings = p.Bookings
            .Where(q => q.IsDeleted == false && q.User.IsDeleted == false)
            .Select(r => new {
                Bookings = r,
                User = r.User
            })
            .AsEnumerable()
            .Select(q => q.Bookings)
    })
    .AsEnumerable()
    .Select(p => p.Concerts)
    .ToList();

However, this is still returning all records and not filtering out the ones where IsDeleted = true. 但是,这仍然会返回所有记录,而不是过滤掉IsDeleted = true的记录。 Anyone have any ideas, or suggestions how I can clean up this monstrous query? 任何人有任何想法,或建议如何清理这个怪异的查询?

I have also tried a method similar to this (http://blogs.msdn.com/b/alexj/archive/2009/06/02/tip-22-how-to-make-include-really-include.aspx), which again fails (returns all bookings even deleted ones): 我也尝试过类似的方法(http://blogs.msdn.com/b/alexj/archive/2009/06/02/tip-22-how-to-make-include-really-include.aspx) ,再次失败(返回所有预订甚至删除的):

var concertsQuery = (ObjectQuery<Concert>)_context.Concerts
    .Where(p => p.UserId == userId
        && p.IsDeleted == false
        && p.Bookings.Any(q => q.IsDeleted == false && q.User.IsDeleted == false)
    );

var concerts = concertsQuery.Include("Bookings").Include("Bookings.User").ToList();

Get rid of those AsEnumerable they will turn your query to linq-to-objects: 摆脱那些AsEnumerable他们会将你的查询转为linq-to-objects:

var concerts = _context.Concerts
    .Where(p => p.AdministratorId == adminId && p.IsDeleted == false)
    .Select(p => new {
        Concerts = p,
        Bookings = p.Bookings
            .Where(q => q.IsDeleted == false && q.User.IsDeleted == false)
            .Select(r => new {
                Bookings = r,
                User = r.User
            })
    })
    .ToList();

So, the way I've managed to resolve this issue is by running the LINQ query as per Ladislav's answer, but then using the anonymous object to re-attach the individual objects to their correct relational properties as below: 因此,我设法解决此问题的方法是按照Ladislav的回答运行LINQ查询,然后使用匿名对象将各个对象重新附加到其正确的关系属性,如下所示:

var concertResult = new List<Concert>();

foreach (var concertObject in concerts)
{
    var concert = concertObject.Concert;

    foreach (var bookingObject in concertObject.Bookings)
    {
        var booking = bookingObject.Booking;
        booking.User = bookingObject.User;
        concert.Bookings.Add(booking);
    }
    concertResult.Add(concert);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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