【问题标题】:How would I use an anonymous result type for an expression delegate for LINQ to SQL?如何将匿名结果类型用于 LINQ to SQL 的表达式委托?
【发布时间】:2020-02-19 22:50:03
【问题描述】:

我有一个现有的 LINQ to SQL 查询,我试图在其中允许不同的分组:

var result= dc.Report_Data
                .Where(x => x.Year == Year)
                .Where(x => x.Month >= Month)
                .GroupBy(grouping)
                .Select(g => new ReportViewModel(){
                    Month = g.Key.Month,
                    Option1 = g.Key.Option1, 
                    Option2 = g.Key.Option2,
                    Amount = g.Sum(x => x.Amount)
                })
                .ToList();

我需要允许根据外部参数对不同的属性集进行分组。我设置了一个默认值,然后使用这样的条件:

Expression<Func<Report_Data, TResult>> grouping = g => new {g.Month, Option1 = g.prop1, Option2 = g.prop2};

if (userParameter == "X"){
    grouping = g => new {g.Month, Option1 = g.prop3, Option2 = g.prop4};
} else if (userParameter == "Y") {
    grouping = g => new {g.Month, Option1 = g.prop5, Option2 = g.prop6};
}

然后我将grouping 传递给上面的查询。问题是我在分组中有一个匿名类型,当我使用TResult 作为结果类型时出现Expression&lt;Func&lt;Report_Data, TResult&gt;&gt; 错误。

有没有办法使用这种表达式委托格式并指定通用或匿名结果类型? (最好不必为每种结果类型创建一个类) 还是我应该通过其他机制允许不同的分组?

【问题讨论】:

  • 大多数匿名类型的问题都可以通过定义自己的命名类型来解决。我不是 100% 确定,但我认为你在这里构造不同的匿名类型,因为你在两个地方定义它。但是要将其分配给分组,它们必须相等。除了将分组作为变量之外,您还可以将“if”放在 IQueryable 链中。
  • 我不反对。如果可能,我尝试使用泛型的原因是因为这是我正在修改的现有代码库,并且我将更新多个使用匿名类型的查询。因此,如果我可以减少改变而侥幸,我愿意这样做。如果最终证明情况更糟,我将通过并开始创建一堆命名类型。
  • 您不能让(非泛型)方法返回匿名类型,并且您不能后退(或上一级)因为Grouping 返回一个IGrouping,这取决于匿名类型也是如此。但是您可以通过将Option1Option2 设为固定类型并将各种prop* 字段转换为该类型(如果它们不相似)来标准化密钥类型。 ReportViewModel.Option1ReportViewModel.Option2有哪些类型?

标签: c# sql linq lambda delegates


【解决方案1】:

根据building LINQ Queries 上这篇博文的解释,我找到了如下解决方案:

扩展 LINQ:

public static class Linq {
    public static Expression<Func<T, R>> 
        Expr<T, R>(Expression<Func<T, R>> f) {
        return f;
    }
}

然后可以这样设置分组:

var grouping = Linq.Expr((Report_Data g) => new {g.Month, Option1 = g.prop1, Option2 = g.prop2});

if (userParameter == "X") {
    grouping = Linq.Expr((Report_Data g) => new {g.Month, Option1 = g.prop3, Option2 = g.prop4});
} else if(userParameter == "Y") {
    grouping = Linq.Expr((Report_Data g) => new {g.Month, Option1 = g.prop5, Option2 = g.prop6});
}

【讨论】:

    猜你喜欢
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多