20

I'm having trouble. I can't understand existing answers to this on Stack Overflow and am too new to LINQ to SQL to be able to nut it out myself.

See this SQL:

select p.Name as ProductName, SUM(o.NumberOf) as TotalOrdered from [Order] o
  join [Product] p on o.ProductId = p.Id
  group by p.Name

Returns a nice 2-column table with product names on the left and the total number that product which have been ordered (across all orders) in the right column. How can I duplicate this in LINQ to SQL?

Here is what I've got so far:

var ctx = new DataClasses1DataContext();
var totalProducts = (from o in ctx.Orders
                     join p in ctx.Products on o.ProductId equals p.Id
                     select new { p.Name, o.NumberOf })
    .GroupBy(t => t.Name)
    .Select(g => g.Key, ... );

What goes at the ... ?

3 Answers 3

40

It looks to me like you want:

.Select(g => new { ProductName = g.Key, TotalOrdered = g.Sum(x => x.NumberOf) })

You can do your whole query as either a single query expression or without using query expressions at all though:

var totalProducts = ctx.Orders
                       .Join(ctx.Products, o => o.ProductId, p => p.Id,
                             (o, p) => new { p.Name, o.NumberOf })
                       .GroupBy(t => t.Name,
                                pair => pair.Name, // Key selector
                                pair => pair.NumberOf, // Element selector
                                (key, numbers) => new { 
                                    ProductName = key,
                                    TotalOrdered = numbers.Sum()) 
                                });

Or:

var totalProdcuts = from o in ctx.Orders
                    join p in ctx.Products on o.ProductId equals p.Id
                    group o.NumberOf by p.Name into g
                    select new { ProductName = g.Key, TotalOrdered = g.Sum() };
Sign up to request clarification or add additional context in comments.

9 Comments

This is correct. Have just checked. Thank you for helping me in my brain-dead moment.
@Lisa: Your SQL originally grouped by NumberOf as well... anyway, see my latest edit.
Thanks for quick response and how it is done properly without mixing syntaxes as I did -- I just got stuck. Nice to see it can be done entirely with either but a single query expression would be the choice for this task.
@JonSkeet , How would you write the same using lambda expression?
@BilalFazlani: Well for the grouping and selection part, just call GroupBy; the tricky bit is with the Join as well, which uses transparent identifiers. I would try to use query expressions for code like this - why do you particularly want to use a lambda expression here?
|
6
TotalOrdered = g.Sum(o => o.NumberOf)

make use of above for .... than statement might be

   select new { ProductName=  g.Key, TotalOrdered  = g.Sum(o => o.NumberOf) };

var query = from o in ctx.Orders
            join p in ctx.Products on 
            o.ProductId equals p.Id
            group o by new { p.Name, o.NumberOf } into g
            select new { ProductName=  g.Key, TotalOrdered  = g.Sum(o => o.NumberOf) };

2 Comments

I understand how to obtain the sum. What was confusing me was how to get it into a projection.
Yes this also works perfectly. I think it was what I was looking for in the beginning. It's much more elegant than by mix of LINQ-to-SQL and Linq extensions.
1

Just pasting this here in case it is helpful to know how this could be achieved through GroupJoin method:

var totalProducts = ctx.Products.GroupJoin(ctx.Orders,
    outerKeySelProduct => outerKeySelProduct.Id,
    innerKeySelOrder => innerKeySelOrder.ProductId,
    (outerKeySelProduct, innerKeySelOrder) => new
    {
        ProductName = outerKeySelProduct.Name,
        TotalOrdered = innerKeySelOrder.Select(n => n.NumberOf).Sum()
    });

Happy for it to be edited if it can be improved.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.