如何使用最少的代码重复将不同的GroupBy存储在一个变量中?

时间:2015-09-23 13:57:41

标签: c# asp.net entity-framework

我有以下代码:

  var newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds,
                    null, widgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value)
                    .GroupBy(s => new { widgetId = s.widgetId, ProductId = s.ProductId });

如果我有条件显示所有我想从GroupBY中取出以下内容:

WidgetId = s.WidgetId

现在它将是:

var newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds,
                    null, widgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value)
                    .GroupBy(s => new {ProductId = s.ProductId });

有很多代码依赖于newProducts,当我创建了一个if语句并将var newProducts放在了outerscrope中时,它会阻止所有工作。

我知道这可能是个愚蠢的问题,但我怎么能用最少的重复代码来做呢?

当我这样做时,我是否宣布变量是错误的:

var newProducts;     
 if(model.allWidgets)
    {newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds,
                            null, WidgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value)
                            .GroupBy(s => new {ProductId = s.ProductId });}
else
{
newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds,
                        null, WidgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value)
                        .GroupBy(s => new { WidgetId = s.WidgetId, ProductId = s.ProductId });
}

3 个答案:

答案 0 :(得分:4)

当model.allWidgets为true时,您可以将GroupBy更改为忽略s.WidgetId:

query.GroupBy(s => new { WidgetId = model.allWidgets ? 0 : s.WidgetId, ProductId = s.ProductId });

答案 1 :(得分:2)

LINQ Conditional Group开始,您可以为分组(WidgetId = 0)添加“null”,从而导致GroupBy在两种情况下都返回相同的匿名分组类型:

var newProducts =  _summaryRepository.GetFilteredSummaries(...)
                                     .Where(s => ...)

var groupedProducts = newProducts.GroupBy(s => 
{
    if(model.allWidgets)
    {
        return new 
        {
            ProductId = s.ProductId,
            WidgetId = 0,
        };
    }
    else
    {
        return new 
        {
            ProductId = s.ProductId,
            WidgetId = s.WidgetId,
        };
    }
});

当然,作为just-added answer indicates,使用条件运算符可以大大减少这一点:

var groupedProducts = newProducts.GroupBy(s => 
    new 
    {
        ProductId = s.ProductId,
        WidgetId = model.allWidgets ? 0 : s.WidgetId,
    });

此类型仍然是匿名的,因此无法直接从您的代码访问,因此为了从方法返回它,请引入一个类来保存该组:

public class ProductGrouping
{
    public int ProductId { get; set; }
    public int? WidgetId { get; set; }
}

public IGrouping<ProductGrouping, Summary> GetGroupedSummaries()
{
    return _summaryRepository.GetFilteredSummaries(...)
                             .Where(s => ...)
                             .GroupBy(s => new ProductGrouping
                             {
                                ProductId = s.ProductId,
                                WidgetId = model.allWidgets ? (int?)null : s.WidgetId,
                             });
}

答案 2 :(得分:1)

您尝试做的事情实际上是不可能的,因为您的2个查询会返回不同的匿名类型,除非您愿意将结果分配回object类型的变量,这似乎不太有用(或dynamic,但是你失去了使用LINQ的编译时间好处。

为了能够使用var关键字,编译器必须能够确定声明类型,这意味着您必须在声明变量的位置提供赋值。

正如Implicitly Typed Local Variables的文档中所述:

  

var关键字指示编译器从初始化语句右侧的表达式 推断变量 的类型。

还有......

  

重要的是要了解 var关键字并不代表“变种” ,并不表示该变量是松散输入的,或者是界。它只是意味着编译器确定并分配最合适的类型。