Query expressions to Lambda Syntax? - linq

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
});

Related

Linq How to group joined queries

I am newbee and can join two datasets. I want to group these by OrderNo query. How can I manage that?
var result = context.Order
.Join(context.OrderDetails
, od => od.OrderId
, o => o.OrderId
, (o, od) => new {
o.OrderNo, od.ProductName, o.OrderDate
})
.Select(s => s);
try this
var result = context.Order
.Join(context.OrderDetails
, od => od.OrderId
, o => o.OrderId
, (o, od) => new {
o.OrderNo, od.ProductName, o.OrderDate
})
.GroupBy(p => new{
o.OrderNo
})
.Select(s => s);

Where, Select and Single in Linq: What is the most efficient use with ASP.NET Core?

As far as I know, there is not a way to select information from the output of a Single statement. It means it is not possible to write like this:
var playerIdName = context.Players
.Single(p => p.ID == playerID)
.Select(p => new
{
ID = p.ID,
Name = p.Name + " " + p.LastName,
});
Instead, you can write in this two ways:
var playerIdName = context.Players
.Select(p => new
{
ID = p.ID,
Name = p.Name + " " + p.LastName,
})
.Single(p => p.ID == playerID);
or
var playerIdName = context.Players
.Where(p => p.ID == playerID)
.Select(p => new
{
ID = p.ID,
Name = p.Name + " " + p.LastName,
}).Single(p => p.ID == playerID);
but both of them seem tremendously unefficient. Any suggestion of what is the efficiency of this two statements and what is the better way to get information from a selected item apart to make two different statements like:
var player = context.Players
.Single(p => p.ID == playerID);
var playerIdName = new
{
ID = player .ID,
Name = player .Name + " " + player .LastName,
};
How about:
var playerIdName = context.Players
.Where(p => p.ID == playerID)
.Take(1)
.Select(p => new
{
ID = p.ID,
Name = p.Name + " " + p.LastName,
})
.Single();
Take(1) will get the first object that matches the filter in the Where(), Select() projects it, and Single() then executes the whole set.
The iterator in Where() will only iterate until it finds the first match.
I did not test if EF is able to convert this to SQL.

LINQ - Group by lambda expression

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 () })

LINQ-2-SQL How-To "Reuse" sub selections

Let's assume:
I have an EVENT table
I have a CLIENT table
And ADDRESS table have some column: UnitNo, StreetNo, StreetName, City, AddressType etc
A CLIENT has many EVENTs and CLIENT can have many ADDRESSes also
So if I want to query list of events with client HOME address street name, I just go
var qry = db.Events
.Select(evt => new {
EventAddress =
evt.Client
.Addresses
.FirstOrDefault(a => a.AddressType.Equals("HOME")).StreetName
});
However, if I want to get the full address I will need to concatenate sereval address fields. At the moment I am trying something like
var qry = db.Events
.Select(evt => new {
EventAddress =
evt.Client
.Addresses
.FirstOrDefault(a => a.AddressType.Equals("HOME")).StreetNo + " " +
evt.Client
.Addresses
.FirstOrDefault(a => a.AddressType.Equals("HOME")).StreetName + " " +
evt.Client
.Addresses
.FirstOrDefault(a => a.AddressType.Equals("HOME")).City
});
It doesn't work and looks ugly too
Is there a better way to make the
evt.Client.Addresses.FirstOrDefault(a => a.AddressType.Equals("HOME")) "reusable" so I can just go
var qry =
db.Events
.Select(evt => new {
EventAddress =
STUFF.StreetNo + " " + STUFF.StreetName + " " + STUFF.City
});
Many thanks in advance!
Hugh
UPDATE:
Thanks Ilian for the answer, it works well. And based on that I have created the extension version of the answer
var qry =
db.Events
.Select(evt => new {
EventAddress =
db.Addresses.Select(a => new
{
ClientId = a.ClientId,
AddressType = a.AddressType,
FullAddress = (a.addStreetNo ?? "") + (a.addStreetName ?? "")
})
.FirstOrDefault(a => a.ClientId == e.Client.ClientId && a.AddressType.Equals("HOME"))
.FullAddress
});
Use the query syntax:
var qry =
from evt in db.Events
let firstAddress = evt.Client.Addresses.FirstOrDefault(a => a.AddressType.Equals("HOME"))
where firstAddress != null
select new
{
EventAddress = firstAddress.StreetNo + " " +
firstAddress.StreetName + " " +
firstAddress.City
}

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