0

我想做一些感觉应该很简单的事情,但结果却让我很头疼。我Select来自一个IQueryable而不是创建一个新对象,我想“调整”我正在投影的那个。这是我想要做的(context是 a DbContext,我使用的是代码优先方法):

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

这很好,因为 Entity Framework 不必实际获取User与每个事件关联的所有实体,并且可以使用聚合COUNT函数来简单地获取用户数量。但是,它不起作用,因为该IQueryable版本需要Select一个没有方法体的 lambda 语句,可以转换为表达式树。因此,虽然上述方法不起作用,但它确实:

.Select(evnt => evnt)

...所以这样做:

.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的 on eventsToReturnData,这一次工作,因为eventsToReturnData是一个IEnumerable(所以 lambda 可以有一个方法body),只是通过设置我从第一个查询中获得的整数来调整Event对象。UnmappedUsersCount

有没有更简单或更优雅的方法来做到这一点?我想避免 EF 必须为每个事件检索所有用户,因此仅使用's方法Event.Users.Count()返回的内容是没有好处的。IQueryableSelect

4

1 回答 1

1

您可以利用Expression该类在运行时构建一棵树,但这需要大量工作和代码,只有在您必须多次执行此类操作时才合理。

如果这种模式在您的代码中仅出现一次或很少出现,这是您能做的最好的事情。

于 2012-10-09T23:06:42.033 回答