首页 > 解决方案 > Entity Framework Core:使用计算字段分组

问题描述

我正在尝试编写查询。到目前为止我所拥有的如下所示。

var x = from d in DbContext.StorageDetails

        let state = (d.ReleaseDate.HasValue && d.ReleaseDate < date) || (d.TakeOrPayEndDate.HasValue && d.TakeOrPayEndDate < date) ?
                StorageState.Closed :
                (d.RailcarNumber == null || d.RailcarNumber == string.Empty) ?
                    d.TakeOrPayStartDate.HasValue ? StorageState.TakeOrPay : StorageState.Open :
                    (d.ArrivalDate.HasValue && d.ArrivalDate <= date) ? StorageState.Filled : StorageState.EnRoute

        group d by new
        {
            d.CustomerId,
            d.Customer.Name,
            d.LocationId,
            d.Location.City,
            d.Location.State
        } into g

        select new
        {
            // ...
        };

给我带来麻烦的部分是我想在state每个项目中包含计算值。我不想按此值进行分组,但我希望能够对其进行求和。

// Note: This is after my group statement
select new
{
    // state is a let variable and not part of x!
    TotalOpen = g.Sum(x => x.state == StorageState.Open),
    TotalClosed = g.Sum(x => x.state == StorageState.Closed),
    // Etc.
};

有没有办法做到这一点?我似乎无法selectgroup by. 如何将此计算字段插入每个项目?

注意:StorageState是一个枚举。我可以很容易地将它转换为int所有这些表达式。我可以弄清楚那部分,但弄清楚它与我的问题是分开的。

标签: c#entity-frameworkasp.net-core.net-coreentity-framework-core

解决方案


这里似乎发生了两件事:

  1. StorageDetails以某种方式查询DbContext每个找到的 item( d),有一些执行正在被处理以确定state...
  2. state为每个确定d,然后对所有的d' 进行分组,然后在仅d选择几个属性之后...

这可能是另一种方法:

var x = DbContext.StorageDetails
    .GroupBy(d => new
    {
        d.CustomerId,
        d.Name,
        d.LocationId,
        d.City,
        d.State
    }).Select(d => new
    {
        d.CustomerId,
        d.Name,
        d.LocationId,
        d.City,
        d.State,
        d.state = getState(d)
    }).ToList();

int getState(d) 
{
    return (d.ReleaseDate.HasValue && d.ReleaseDate < date) || (d.TakeOrPayEndDate.HasValue && d.TakeOrPayEndDate < date) ?
                StorageState.Closed :
                (d.RailcarNumber == null || d.RailcarNumber == string.Empty) ?
                    d.TakeOrPayStartDate.HasValue ? StorageState.TakeOrPay : StorageState.Open :
                    (d.ArrivalDate.HasValue && d.ArrivalDate <= date) ? StorageState.Filled : StorageState.EnRoute;
}

var TotalOpen = x.Count(x => x.state == StorageState.Open),
var TotalClosed = x.Count(x => x.state == StorageState.Closed)

基本上,您首先从数据库组中获取数据。分组后,然后选择特定属性并引入一个名为state... 但是状态是计算的,使用另一个函数从数据库中获取一行返回一个值,enum StorageState就像你在问题上所做的那样。然后将结果作为列表返回。

只有在您拥有列表之后,才能更轻松地检查返回的哪些行包含一个openclosed...

现在您可以进行正常循环并遍历您的x和 计算TotalClosedTotalClosed


推荐阅读