LINQ - Group by lambda expression - linq

Say I have the following:
var OrderCounts = from o in Orders
group o by o.CustomerID into g
select new {
CustomerID = g.Key,
TotalOrders = g.Count()
};
How can this be converted to a Lambda expression

var OrderCounts = customers
.GroupBy (o => o.CustomerID)
.Select (o => new { CustomerID = o.Key, TotalOrders = o.Count () })

Related

Contat 2 Lists from different tables into 1 and use AsQueryable()

Attempting to return the below 2 lists into something I can then query against.
var people = (from c in _context.FollowingPeople
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId,
Person = (from p in _context.SocialMediaPeople
where p.Id == c.SocialMediaId
select new Models.SocialMediaPeople
{
Id = p.Id,
Photo = p.Photo
}).FirstOrDefault()
});
var generic = (from c in _context.FollowingGeneric
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId,
Person = null
});
var temp = people.Concat(generic).ToList();
//var data = temp.AsQueryable();
if (!string.IsNullOrEmpty(filter))
{
data = data.Where(filter);
}
data = data.Where(x => x.ClientId == ClientId);
return await data
.GetPaged(page, pageSize);
I have tried join, concat, even Zip but it results in various errors such as
(Unable to translate set operation after client projection has been applied. Consider moving the set operation before the last 'Select' call.)
So I finally got this working, the trick is to not perform any queries on the data until AFTER the concat. Th below works...
var queryA =
from c in _context.Set<FollowingPeople>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var queryB =
from c in _context.Set<FollowingGeneric>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var queryC =
from c in _context.Set<FollowingPublication>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var data = (from v in queryA.Union(queryB).Union(queryC)
select new Models.Following.FollowingModel
{
Id = v.Id,
MediaTypeId = v.MediaTypeId,
Title = v.Title,
ClientId = v.ClientId,
})
.AsNoTracking()
.AsQueryable();
data = data.Where(x => x.ClientId == ClientId);
return await data.GetPaged(page, pageSize);

Query expressions to Lambda Syntax?

How can I change this query expression to lambda expression:
var dataUser = from cm in ConsumerName
join c in Consumer on cm.ConsumerId equals c.Id
join cua in ConsumerAccount on cm.ConsumerId equals cua.ConsumerId
join bd in BankDetail on cm.ConsumerId equals bd.ConsumerId
join cpm in CardPayment on cm.ConsumerId equals cpm.ConsumerId
where cm.ConsumerId == consumerId
select new { AccountNumber=bd.AccountNumber,CardNumber= cpm.CardNumber, Name = cm.FirstName + " " + cm.MiddleName + " " + cm.LastName, Email = c.Email, AccountId = cua.AccountId };
Simple, auto-converted by Resharper
var dataUser =
ConsumerName.Join(Consumer, cm => cm.ConsumerId, c => c.Id, (cm, c) => new { cm, c })
.Join(ConsumerAccount, #t => cm.ConsumerId, cua => cua.ConsumerId, (#t, cua) => new { #t, cua })
.Join(BankDetail, #t => cm.ConsumerId, bd => bd.ConsumerId, (#t, bd) => new { #t, bd })
.Join(CardPayment, #t => cm.ConsumerId, cpm => cpm.ConsumerId, (#t, cpm) => new { #t, cpm })
.Where(#t => cm.ConsumerId == consumerId)
.Select(
#t =>
new
{
AccountNumber = bd.AccountNumber,
CardNumber = cpm.CardNumber,
Name = cm.FirstName + " " + cm.MiddleName + " " + cm.LastName,
Email = c.Email,
AccountId = cua.AccountId
});

Getting the 1st value in a subset of data

I have a result coming back from a LINQ statement that looks like this:
Id dataId dataVal
A 1 1000
A 2 2000
A 3 3000
A 3 3001
A 3 3002
What I'd like is to just get the 1st item (dataId = 3 and dataVal = 3000)
Here is my query that is generating the above result:
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.Select(x=> new
{
Id = x.Id,
DataId = x.dataId,
DataValue = x.DataValue
}).ToList().Distinct();
Do I need to do some grouping or is there an easier way?
Group your items by dataId, and then select first item from each group:
var myIds = (from a in myList
where ListIds.Contains(a.dataId)
group a by a.dataId into g
let firstA = g.OrderBy(x => x.DataValue).First()
select new {
Id = firstA.Id,
DataId = g.Key,
DataValue = firstA.DataValue
}).ToList();
Or with extension methods (it returns first item in original order):
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.GroupBy(a => a.dataId)
.Select(g => new
{
Id = g.First().Id,
DataId = g.Key,
DataValue = g.First().DataValue
}).ToList();
Use .FirstOrDefault() after the Select
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.Select(x=> new
{
Id = x.Id,
DataId = x.dataId,
DataValue = x.DataValue
}).FirstOrDefault();

LINQ; how to get record with max date with join?

How can I do this in LINQ?
select
*
from customer c
left join order o on o.CustomerID = c.CustomerID
where o.OrderDate = (select MAX(OrderDate) from order where CustomerID = o.CustomerID )
not worried about dups as there will always only be one order per day.
I got as far as the left join in LINQ, but not sure how or where to put the subquery in.
var query = from customer in clist
from order in olist
.Where(o => o.CustomerID == customer.CustomerID)
select new {
customer.CustomerID,
customer.Name,
customer.Address,
Product = order != null ? order.Product : string.Empty
};
FINAL SOLUTION:
var query = from customer in clist
from order in olist
.Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==
olist.Where(o1 => o1.CustomerID == customer.CustomerID).Max(o1 => o1.OrderDate)
)
select new {
customer.CustomerID,
customer.Name,
customer.Address,
order.Product,
order.OrderDate
};
Another solution without any lambdas
var query = from customer in clist
from order in olist
where order.CustomerID == customer.CustomerID && order.OrderDate ==
(from o in olist
where o.CustomerID == customer.CustomerID
select o.OrderDate).Max()
select new {
customer.CustomerID,
customer.Name,
customer.Address,
order.Product,
order.OrderDate
};
This is more or less a literal translation
var query = from customer in clist
from order in olist
.Where(o => o.CustomerID == customer.CustomerID &&
o.OrderDate == olist
.Where(o => o.CustomerID == customer.CustomerID)
.Select(o => o.OrderDate).Max())
select new {
customer.CustomerID,
customer.Name,
customer.Address,
Product = order != null ? order.Product : string.Empty
};
but I would rewrite to
var query = from customer in clist
from order in olist
.Where(o => o.CustomerID == customer.CustomerID)
.OrderByDescending(o => o.OrderDate).Take(1)
select new {
customer.CustomerID,
customer.Name,
customer.Address,
Product = order != null ? order.Product : string.Empty
};
How does this work for you?
var query =
from customer in clist
join order in olist
on customer.CustomerID equals order.CustomerID
into orders
select new
{
customer.CustomerID,
customer.Name,
customer.Address,
Product = orders
.OrderByDescending(x => x.OrderDate)
.Select(x => x.Product)
.FirstOrDefault() ?? String.Empty
};

LINQ lambda expression for many-to-one inner join involving max()

I have the following schema:
Table1
ID int
Table2
ID int
Table1ID int
Datetime datetime
Table3
ID int
Table2ID int
Name varchar(255)
All columns are not null. How do I write the following SQL query in LINQ using lambda expressions?
select Table1.*
from Table2
inner join (
select Table1ID, max(Datetime) as Datetime
from Table2
group by Table1ID
) a on Table2.Table1ID = a.Table1ID and Table2.Datetime = a.Datetime
inner join Table3 on Table2.ID = Table3.Table2ID
inner join Table1 on Table1.ID = Table2.Table1ID
where Name = 'me'
EDIT:
I am using LINQ to EF. I have tried
var myEntities = new MyEntities();
var a = myEntities.Table2.Select(x => new { x.Id, x.Datetime }).GroupBy(x => x.Id).Select(x => new { Id = x.Key, Datetime = x.Max(y => y.Datetime) });
var b = myEntities.Table2.Join(a.ToList(), x => new { Id = x.Table1Id, x.Datetime }, y => new { y.Id, y.Datetime }, (x, y) => x.Id);
return myEntities.Table3.Where(x => x.Name == "me" && b.Contains(x.Table2Id)).Select(x => x.Table2.Table1).ToList();
but it comes back with
System.NotSupportedException: Unable to create a constant value of type 'Anonymous type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
highlighting the last line above. The stack trace shows it is ToList() throwing this exception.
I figured it out; it was that
var b = myEntities.Table2.Join(a.ToList(),
should be
var b = myEntities.Table2.Join(a,
Also, the query should be
var myEntities = new MyEntities();
var a = myEntities.Table2.Select(x => new { x.Table1Id, x.Datetime }).GroupBy(x => x.Table1Id).Select(x => new { Table1Id = x.Key, Datetime = x.Max(y => y.Datetime) });
var b = myEntities.Table2.Join(a, x => new { x.Table1Id, x.Datetime }, y => new { y.Table1Id, y.Datetime }, (x, y) => x);
return b.Join(myEntities.Table3, x => x.Id, y => y.Table2Id, (x, y) => new { x.Table1, y.Name }).Where(x => x.Name == "me").Select(x => x.Table1).ToList();

Resources