使用Select子句调整IQueryable的序列元素?

时间:2012-10-09 23:00:29

标签: c# sql entity-framework ef-code-first

我想做一些感觉应该非常简单的事情,但事实证明这是一件非常令人头痛的事情。我是Select来自IQueryable,而不是创建一个新对象,我想“调整”我正在投影的那个。这是我想要做的(contextDbContext,我正在使用代码优先方法):

var eventsToReturn =
    ((IQueryable<Event>)
        context.Events
        .OrderByDescending(evnt => evnt.TakesPlaceOn)
        .Skip(startAt)
        .Take(numberToReturn)
    )
    .Select(evnt =>
        {
            evnt.UnmappedUsersCount = evnt.Users.Count();
            return evnt;
        }
    )
    .ToList();

这很好,因为实体框架不必实际获取与每个事件关联的所有User实体,并且可以使用聚合COUNT函数来简单地获取用户数。但是,它不起作用,因为IQueryable Select版本的.Select(evnt => evnt) 想要一个没有方法体的lambda语句,可以将其转换为表达式树。因此,虽然上述方法不起作用,但这样做:

.Select(evnt => evnt.Users.Count())

......这样做:

var eventsToReturnData =
    ((IQueryable<Event>)
        context.Events
        .OrderByDescending(evnt => evnt.TakesPlaceOn)
        .Skip(startAt)
        .Take(numberToReturn)
    )
    .Select(evnt =>
        new {
            Event = evnt,
            UnmappedUsersCount = evnt.Users.Count()
        }
    )
    .ToList();

var eventsToReturn = eventsToReturnData
    .Select(evntData => {
        evntData.Event.UnmappedUsersCount = evntData.UnmappedUsersCount;
        return evntData.Event;
    })
    .ToList();

我已经解决了这个问题,但我的方式似乎相当啰嗦。这是我的方法:

Event

所以我将主int对象投射到一个匿名对象中,以及我要添加到其中的一个小Select,然后再做一个全新的eventsToReturnData eventsToReturnData上的IEnumerable,因为EventUnmappedUsersCount(因此lambda可以有一个方法体),只需通过设置{来调整Event.Users.Count()对象{1}}我从第一个查询得到的整数。

有更简单或更优雅的方法吗?我想避免EF必须为每个事件检索所有用户,因此仅使用IQueryable Select {{1}}方法返回的内容就不行了。

1 个答案:

答案 0 :(得分:1)

您可以利用Expression类在运行时构建一个树,但这样做的工作和代码非常多,只有在您不得不多次执行此类操作时才能证明这一点。

如果此模式只出现一次或很少出现在您的代码中,那么这是您可以做的最好的。