Use Grouping with LINQ Query Syntax and Method Syntax in C#
LINQ (Language-Integrated Query) is a powerful feature in C# that provides a unified way to query and manipulate data from different data sources. LINQ supports two syntax styles: query syntax and method syntax. In this blog post, we’ll explore both syntax styles and provide examples of their usage.
LINQ Query Syntax
LINQ query syntax resembles SQL-like syntax and allows you to write queries in a declarative and intuitive way. Let’s dive into an example using LINQ query syntax:
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = from number in numbers
where number % 2 == 0
select number;
In this example, we have a collection of numbers. The LINQ query selects only the even numbers from the collection using the where
clause and projects them using the select
clause. The result is stored in the evenNumbers
variable.
LINQ Method Syntax
LINQ method syntax, also known as fluent syntax, is a more concise and method chaining-oriented style. It allows you to chain together various LINQ operators to perform the desired operations. Here’s the equivalent example using LINQ method syntax:
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(number => number % 2 == 0);
In this version, the LINQ operators are invoked as extension methods on the collection (numbers
). The Where
operator filters the collection based on the provided condition.
Examples: Grouping Promotions by Label
Let’s consider an example where we have a collection of stores, and each store has a collection of promotions. We want to group all the store’s promotions by their label.
public record Store(int StoreId, ICollection<Promotion> Promotions);
public record Promotion(int PromotionId, string Label, float Discount);
List<Store> stores = GetStores();
// LINQ Query Syntax
var groupedPromotionsQuery = from store in stores
from promotion in store.Promotions
group promotion by promotion.Label into labelGroup
orderby labelGroup.Key
select new
{
Label = labelGroup.Key,
Promotions = labelGroup
};
// LINQ Method Syntax
var groupedPromotionsMethod = stores
.SelectMany(store => store.Promotions, (store, promotion) => new { store, promotion })
.GroupBy(x => x.promotion.Label)
.OrderBy(g => g.Key)
.Select(g => new
{
Label = g.Key,
Promotions = g.Select(x => x.promotion)
});
public List<Store> GetStores() =>
new List<Store>
{
new Store(1, new List<Promotion>
{
new Promotion(1, "Label1", 0.2f),
new Promotion(2, "Label2", 0.1f),
new Promotion(3, "Label1", 0.3f),
new Promotion(4, "Label3", 0.15f),
new Promotion(5, "Label2", 0.25f),
}),
new Store(2, new List<Promotion>
{
new Promotion(6, "Label2", 0.2f),
new Promotion(7, "Label1", 0.15f),
new Promotion(8, "Label3", 0.1f),
new Promotion(9, "Label1", 0.3f),
new Promotion(10, "Label2", 0.25f),
})
};
In the above example, we have two variations of the LINQ query that group promotions by their label. The groupedPromotionsQuery
uses query syntax, while the groupgroupedPromotionsMethod
uses method syntax.
You can then loop through the results with a foreach
:
foreach (var group in groupedPromotions)
{
Console.WriteLine("Label: " + group.Label);
foreach (var promotion in group.Promotions)
{
Console.WriteLine("PromotionId: " + promotion.PromotionId + ", Discount: " + promotion.Discount);
}
Console.WriteLine();
}
// Label: Label1
// PromotionId: 1, Discount: 0.2
// PromotionId: 3, Discount: 0.3
// PromotionId: 7, Discount: 0.15
// PromotionId: 9, Discount: 0.3
//
// Label: Label2
// PromotionId: 2, Discount: 0.1
// PromotionId: 5, Discount: 0.25
// PromotionId: 6, Discount: 0.2
// PromotionId: 10, Discount: 0.25
//
// Label: Label3
// PromotionId: 4, Discount: 0.15
// PromotionId: 8, Discount: 0.1
Both iterations will produce the same output, displaying the label followed by the details of each promotion within that label’s group.