我正在尝试将一些旧的SQL重写为LINQ to SQL.我有一个带有GROUP BY WITH ROLLUP的sproc但是我不确定LINQ等价物是什么.LINQ有一个GroupBy,但看起来它不支持ROLLUP.
我试图获得的结果的简化示例将是这样的:
+-----------+---------------+--------------------+ | City | ServicePlan | NumberOfCustomers | +-----------+---------------+--------------------+ | Seattle | Plan A | 10 | | Seattle | Plan B | 5 | | Seattle | All | 15 | | Portland | Plan A | 20 | | Portland | Plan C | 10 | | Portland | All | 30 | | All | All | 45 | +-----------+---------------+--------------------+
关于如何使用LINQ to SQL获得这些结果的任何想法?
Ecy*_*yrb 12
我想出了一个更简单的解决方案.我试图让它变得比它需要的更复杂.而不是需要3-5个类/方法我只需要一个方法.
基本上,您自己进行排序和分组,然后调用WithRollup()以获得List<>包含小计和总计的项目.我无法弄清楚如何在SQL端生成小计和总计,所以这些都是通过LINQ to Objects完成的.这是代码:
/// <summary>
/// Adds sub-totals to a list of items, along with a grand total for the whole list.
/// </summary>
/// <param name="elements">Group and/or sort this yourself before calling WithRollup.</param>
/// <param name="primaryKeyOfElement">Given a TElement, return the property that you want sub-totals for.</param>
/// <param name="calculateSubTotalElement">Given a group of elements, return a TElement that represents the sub-total.</param>
/// <param name="grandTotalElement">A TElement that represents the grand total.</param>
public static List<TElement> WithRollup<TElement, TKey>(this IEnumerable<TElement> elements,
Func<TElement, TKey> primaryKeyOfElement,
Func<IGrouping<TKey, TElement>, TElement> calculateSubTotalElement,
TElement grandTotalElement)
{
// Create a new list the items, subtotals, and the grand total.
List<TElement> results = new List<TElement>();
var lookup = elements.ToLookup(primaryKeyOfElement);
foreach (var group in lookup)
{
// Add items in the current group
results.AddRange(group);
// Add subTotal for current group
results.Add(calculateSubTotalElement(group));
}
// Add grand total
results.Add(grandTotalElement);
return results;
}
Run Code Online (Sandbox Code Playgroud)
以及如何使用它的示例:
class Program
{
static void Main(string[] args)
{
IQueryable<CustomObject> dataItems = (new[]
{
new CustomObject { City = "Seattle", Plan = "Plan B", Charges = 20 },
new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Seattle", Plan = "Plan B", Charges = 20 },
new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Seattle", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Portland", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Portland", Plan = "Plan A", Charges = 10 },
new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 },
new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 },
new CustomObject { City = "Portland", Plan = "Plan C", Charges = 30 }
}).AsQueryable();
IQueryable<CustomObject> orderedElements = from item in dataItems
orderby item.City, item.Plan
group item by new { item.City, item.Plan } into grouping
select new CustomObject
{
City = grouping.Key.City,
Plan = grouping.Key.Plan,
Charges = grouping.Sum(item => item.Charges),
Count = grouping.Count()
};
List<CustomObject> results = orderedElements.WithRollup(
item => item.City,
group => new CustomObject
{
City = group.Key,
Plan = "All",
Charges = group.Sum(item => item.Charges),
Count = group.Sum(item => item.Count)
},
new CustomObject
{
City = "All",
Plan = "All",
Charges = orderedElements.Sum(item => item.Charges),
Count = orderedElements.Sum(item => item.Count)
});
foreach (var result in results)
Console.WriteLine(result);
Console.Read();
}
}
class CustomObject
{
public string City { get; set; }
public string Plan { get; set; }
public int Count { get; set; }
public decimal Charges { get; set; }
public override string ToString()
{
return String.Format("{0} - {1} ({2} - {3})", City, Plan, Count, Charges);
}
}
Run Code Online (Sandbox Code Playgroud)