Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法减少这两个linq查询中的重复_C#_Linq_Entity Framework - Fatal编程技术网

C# 有没有办法减少这两个linq查询中的重复

C# 有没有办法减少这两个linq查询中的重复,c#,linq,entity-framework,C#,Linq,Entity Framework,构建一组报告时,必须对不同的字段反复执行相同的操作 public List<ReportSummary> ListProducer() { return (from p in Context.stdReports group p by new { p.txt_company, p.int_agencyId } into g

构建一组报告时,必须对不同的字段反复执行相同的操作

    public List<ReportSummary> ListProducer()
    {
        return (from p in Context.stdReports                    
                group p by new { p.txt_company, p.int_agencyId }
                    into g
                    select new ReportSummary
                    {
                        PKi = g.Key.int_agencyId,
                        Name = g.Key.txt_company,
                        Sum = g.Sum(foo => foo.lng_premium),
                        Count = g.Count()
                    }).OrderBy(q => q.Name).ToList();
    }

    public List<ReportSummary> ListCarrier()
    {
        return (from p in Context.stdReports
                group p by new { p.txt_carrier, p.int_carrierId }
                    into g
                    select new ReportSummary
                    {
                        PKi = g.Key.int_carrierId,
                        Name = g.Key.txt_carrier,
                        Sum = g.Sum(foo => foo.lng_premium),
                        Count = g.Count()
                    }).OrderBy(q => q.Name).ToList();
    }
公共列表ListProducer()
{
返回(来自Context.stdReports中的p
p组由新的{p.txt_公司,p.int_代理ID}
进入g
选择新报告摘要
{
PKi=g.Key.int_agencyId,
Name=g.Key.txt\u公司,
Sum=g.Sum(foo=>foo.lng\U溢价),
Count=g.Count()
}).OrderBy(q=>q.Name).ToList();
}
公共列表ListCarrier()
{
返回(来自Context.stdReports中的p
按新{p.txt_carrier,p.int_carrierId}划分的p组
进入g
选择新报告摘要
{
PKi=g.Key.int\u carrierId,
名称=g.Key.txt\u载体,
Sum=g.Sum(foo=>foo.lng\U溢价),
Count=g.Count()
}).OrderBy(q=>q.Name).ToList();
}

我的脑子里一片空白,不知如何才能把这两个人结合起来

看起来唯一改变的是分组参数的名称。您能否编写一个包装器函数来接受指定分组参数的lambda?或者甚至是一个包装函数,它接受两个字符串,然后构建原始T-SQL,而不是使用LINQ


或者,我不知道这是否会编译,您能否在group语句中对字段进行别名,以便始终以相同的方式引用分组构造,例如
g.Key.id1
g.Key.id2
?然后可以将分组构造传递到
ReportSummary
构造函数中,并在一个位置执行左/右赋值。(但您需要将其作为动态对象传递,因为它是呼叫站点上的匿名对象)

您可以执行以下操作:

public List<ReportSummary> GetList(Func<Record, Tuple<string, int>> fieldSelector)
{
    return (from p in Context.stdReports                    
        group p by fieldSelector(p)
            into g
            select new ReportSummary
            {
                PKi = g.Key.Item2
                Name = g.Key.Item1,
                Sum = g.Sum(foo => foo.lng_premium),
                Count = g.Count()
            }).OrderBy(q => q.Name).ToList();
}
var summary = GetList(rec => Tuple.Create(rec.txt_company, rec.int_agencyId));
或:

当然,您需要用任何类型的
Context.stdReports
来替换
Record


我还没有检查它是否可以编译,但您已经明白了。

因为两个查询之间的所有更改都是组键,所以请将其参数化。因为它是一个复合键(其中有多个值),所以需要创建一个简单的类来保存这些值(使用泛型名称)

在这种情况下,要对其进行参数化,请将键选择器设置为函数的参数。它必须是一个表达式和方法语法才能工作。然后,您可以将其概括为一个函数:

public class GroupKey
{
    public int Id { get; set; }
    public string Name { get; set; }
}

private IQueryable<ReportSummary> GetReport(
    Expression<Func<stdReport, GroupKey>> groupKeySelector)
{
    return Context.stdReports
        .GroupBy(groupKeySelector)
        .Select(g => new ReportSummary
        {
            PKi = g.Key.Id,
            Name = g.Key.Name,
            Sum = g.Sum(report => report.lng_premium),
            Count = g.Count(),
        })
        .OrderBy(summary => summary.Name);
}
公共类组密钥
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
私有IQueryable GetReport(
表达式组(键选择器)
{
返回Context.stdReports
.GroupBy(groupKeySelector)
.选择(g=>newreportsummary
{
PKi=g.Key.Id,
Name=g.Key.Name,
总和=总总和(报告=>报告液化天然气溢价),
Count=g.Count(),
})
.OrderBy(summary=>summary.Name);
}
然后,只需使用适当的键选择器在查询中使用此功能

public List<ReportSummary> ListProducer()
{
    return GetReport(r =>
        new GroupKey
        {
            Id = r.int_agencyId,
            Name = r.txt_company,
        })
        .ToList();
}

public List<ReportSummary> ListCarrier()
{
    return GetReport(r =>
        new GroupKey
        {
            Id = r.int_carrierId,
            Name = r.txt_carrier,
        })
        .ToList();
}
公共列表ListProducer()
{
返回GetReport(r=>
新组密钥
{
Id=r.int\u agencyId,
名称=r.txt_公司,
})
.ToList();
}
公共列表ListCarrier()
{
返回GetReport(r=>
新组密钥
{
Id=r.int\u carrierId,
名称=r.txt\u载体,
})
.ToList();
}

我不知道你为你的实体映射了什么类型,所以我做了一些假设。在您的情况下使用任何合适的方法。

如果使用扩展方法(点表示法)而不是类似sql的查询表示法,则两个查询除了传递给group by的lambda之外看起来都一样。粗略地看一下,我猜只有
Func键选择器
发生了变化,请参见msdn上的。因此,您将有一个
Func myKeySelector
,其余的是通用代码。不知道我说的是否有道理,现在已经很晚了,我在一个新的OSX上,所以我现在不能写任何C。你可以使用表达式树来构建动态查询。请注意,因为这可能是一个查询提供程序,而不是LINQ对象,所以你需要在
表达式中传递
Select
中的匿名类型也会有所不同。只是在它引用分组的方式上有所不同对象在这两种情况下,对象的结构是相同的,所以我认为它可以被推广(有点像它的ME86的答案)
public List<ReportSummary> ListProducer()
{
    return GetReport(r =>
        new GroupKey
        {
            Id = r.int_agencyId,
            Name = r.txt_company,
        })
        .ToList();
}

public List<ReportSummary> ListCarrier()
{
    return GetReport(r =>
        new GroupKey
        {
            Id = r.int_carrierId,
            Name = r.txt_carrier,
        })
        .ToList();
}