How to convert linq query with joins to method syntax? - c#

I want to change this to lambda query in c#
var innerJoinTasinmaz =
from tasin in _context.Tasinmaz
join mahalle in _context.Mahalle on tasin.MahalleID equals mahalle.AreaID
join ilce in _context.Ilce on tasin.CountyID equals ilce.CountyID
join il in _context.Il on tasin.CityID equals il.CityID
select new{
tasinmazID = tasin.TasinmazID,
cityName = il.CityName,
countyName = ilce.CountyName,
areaName = mahalle.AreaName,
ada = tasin.Ada,
parsel = tasin.Parsel,
nitelik = tasin.Nitelik,
adres = tasin.Adres,
isActive = tasin.isActive,
};
I am struggling to write it in Lambda Expression. Any help would be greatly appreciated.

You'll need the Join method which takes four parameters:
the enumerable that you want to join
a selector in the first enumerable
a selector in the second enumerable
a selector for both enumerables
It is compared whether the values from 2 und 3 are the same, and if so, the selector from 4 is used to choose which properties you want to use. In your example, it would look like:
var innerJoinTasinmaz =
_context.Tasinmaz
.Join(_context.Mahalle, x => x.MahalleId, y => y.AreaID, (x, y) => new { tasin = x, mahalle = y })
.Join(_context.Ilce, x => x.CountyID, y => y.CountyId, (x, y) => new { tasin = x.tasin, mahalle = x.mahalle, ilce = y })
.Join(_context.Il, x => x.CityId, y => y.CityId, (x, y) => new
{
tasinmazId = x.tasin.TasinmazID,
cityName = y.CityName,
countyName = x.ilce.CountyName,
areaName = x.mahalle.AreaName,
ada = x.tasin.Ada,
parsel = x.tasin.Parsel,
nitelik = x.tasin.Nitelik,
adres = x.tasin.Adres,
isActive = x.tasin.isActive,
});
You can think about whether method or query syntax is more readable.

Related

convert SQL to LINQ or imporve my query please

I am trying to convert sql to lambda or LINQ but can't simplified yet,
I managed to do it two different lambda but i want it a single query.
SQL query is this :
SELECT PamID, MAX (MaxAmount)
FROM RebateTable
GROUP BY PamID
so far this is working but is there any better way.
var t = from r in RebateList
group r by r.PamID;
var x = from y in t
select new RebateMaxClass
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
You could use this form:
RebateTable.GroupBy(r=>r.PamId).Select(s=>new RebateMaxClass
{
PamId = s.Key,
TotalSale = s.Max(y => y.MaxAmount)
};
The query look good. You could form a single query like this:
var t = from r in RebateList
group r by r.PamId into y
select new
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
But this is not faster. The Query is extended and will ont be executed until is has to.
An alternative is forming the "new LinQ-Style":
var t2 = RebateList.GroupBy(g => g.PamId) // Do a Grouping
var t3 = t2.Select(s => new { PamId = s.Key, TotalSale = s.Max(m => m.MaxAmount) });

How to get a Left Join on Linq

I have this query with Join. This gives me an inner join. What I want to accomplish is a left join.
I tried using DefaultIfEmpty() but I couldn't get it to work. Perhaps I am putting it on the wrong part of the query.
Can anyone point me out to the right way of using DefaultIfEmpty()?
Below is my current query:
var AppList = (de.ComputerUserApplication)
.Where(CUA => CUA.EmployeeID == employeeID)
.DefaultIfEmpty()
.Join(de.ApplicationTypeMasters,
CUA => CUA.RecordType,
ATM => ATM.Code,
(CUA, ATM) => new ApplicationModel
{
ApplicationNo = CUA.ApplicationNo,
ApplicationCode = CUA.RecordType,
ApplicationTypeCode = "",
ApplicationName = ATM.Title + " - " + CUA.Description,
Status = CUA.Status
});
Also, I'm not quite sure if I have the correct query. if you may, below is my original query:
select Cua_ApplicationNo, Cua_Type_Rec, ATM_ApplicationTitle, Cua_Status from ComputerUserApplication
left join ApplicationTypeMaster
on Cua_Type_Rec = ATM_ApplicationCode
where Cua_EmployeeID = 'someID'
You need to use GroupJoin for an outer join; this will work assuming there's 0 or 1 matching ApplicationTypeMaster rows; if more, then you'd need to do a DefaultIfEmpty followed by SelectMany.
de.ComputerUserApplication
.Where(x => x.EmployeeID == employeeID)
.GroupJoin(
de.ApplicationTypeMasters,
CUA => CUA.RecordType,
ATM => ATM.Code,
(CUA, ATM) => new ApplicationModel
{
ApplicationNo = CUA.ApplicationNo,
ApplicationCode = CUA.RecordType,
ApplicationTypeCode = "",
ApplicationName = ATM.SingleOrDefault()?.Title + " - " + CUA.Description,
Status = CUA.Status
}
);
If you don't know how many matching rows there are, then SelectMany will give you the equivalent results as SQL:
de.ComputerUserApplication
.Where(x => x.EmployeeID == employeeID)
.GroupJoin(
de.ApplicationTypeMasters,
CUA => CUA.RecordType,
ATM => ATM.Code,
(x, y) => new { CUA = x, ATMs = y.DefaultIfEmpty() }
).SelectMany(x => x.ATMs.Select(ATM => new ApplicationModel
{
ApplicationNo = x.CUA.ApplicationNo,
ApplicationCode = x.CUA.RecordType,
ApplicationTypeCode = "",
ApplicationName = ATM?.Title + " - " + x.CUA.Description,
Status = x.CUA.Status
}
);
As an aside, this is one of the few times I prefer the query syntax (which does SelectMany without all the noise):
from CUA in de.ComputerUserApplication
join x in de.ApplicationTypeMasters on CUA.RecordType equals x.Code into g
from ATM in g.DefaultIfEmpty()
select new ApplicationModel()
{
ApplicationNo = CUA.ApplicationNo,
ApplicationCode = CUA.RecordType,
ApplicationTypeCode = "",
ApplicationName = ATM?.Title + " - " + CUA.Description,
Status = CUA.Status
};
Using DefaultIfEmpty() you can get left outer join result. And taking care of null.

Grouping and Sum some field with Sub query in LINQ

I'm trying to convert my sql query to linq, i confused about sum and grouping,
this is my query
SELECT
produk.supplier,
SUM(transaksi.jumlah_transaksi),
SUM(transaksi.nominal_transaksi),
operasional.nominal
FROM
transaksi INNER JOIN produk ON transaksi.id_produk = produk.id_produk
LEFT JOIN
(SELECT
operasional.id_supplier,
SUM(nominal) AS nominal
FROM
operasional) operasional
ON operasional.id_supplier = produk.id_supplier
GROUP BY produk.supplier
output should be
like this
Progress
i am just trying with linq query like this without grouping
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
select new
{
id_supplier = o.id_supplier,
nominal = o.nominal
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
and result query from my linq still like this
SELECT
`p`.`supplier`,
`t`.`jumlah_transaksi`,
`t`.`nominal_transaksi`,
`t1`.`nominal`
FROM
`transaksi` `t`
INNER JOIN `produk` `p`
ON `t`.`id_produk` = `p`.`id_produk`
LEFT JOIN `operasional` `t1`
ON `t1`.`id_supplier` = `p`.`id_supplier`
Solved
and this is my full linq
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
group o by o.id_supplier into g
select new
{
id_supplier = g.First().id_supplier,
nominal = g.Sum(o => o.nominal)
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new
{
nama_supplier = x.Key,
jumlah_transaksi = x.Sum(s => s.jumlah_transaksi),
nominal_transaksi = x.Sum(s => s.nominal_transaksi),
biaya_operasional = x.Select(s => s.biaya_operasional).First()
});
Try to use GroupBy (in following code result is your query from code above):
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new {
nama_supplier = x.Key,
sum1 = x.Sum(s => s.jumlah_transaksi),
sum1 = x.Sum(s => s.nominal_transaksi),
nominal = x.Select(s => s.biaya_operasional).First()
})
Code is not checked so use it just as idea.

Linq left join with group join

I have set of Users and Visits. (So user do visits)
Visit have User navigation property.
I need to find the users who don't visit.
I can do this by finding the users who visit, finding all of the users then taking the difference.
I was trying to find a solution which is faster.
This is what I have right now:
var users = _db.Users.AsNoTracking().Include(c => c.City).Where(x => x.City.Id == city);
var groupedUsers = _db.Visits.AsNoTracking().Include(c => c.City).Include(a=>a.VisitedBy).Where(x => x.City.Id == city).GroupBy(x => x.VisitedBy).Select(group => new { VisitedBy = group.Key, Count = group.Count() });
var visitingUsers = groupedUsers.Select(user => user.VisitedBy);
var dif = users.Except(visitingUsers);
However I was trying GroupJoin as below:
var results = _db.Users.Include(c => c.City).Where(c => c.City.Id == city).
GroupJoin(_db.Visits.Include(c => c.City).Include(u => u.VisitedBy), u => u.Id, v => v.VisitedBy.Id, (u, v) => new { User = u , Visits = v })
.Select(o=>o.User);
But this gives me all of the Users, I want the users who don't exist in the Visit set.
Any help?
You may be able to avoid the correlated sub-query in the other answer by actually doing the left join with null check. Here's a quick example:
var A = new [] { new Foo { Bar = 1 }, new Foo { Bar = 2 }};
var B = new [] { new Foo { Bar = 2 }};
var C = from x in A
join y in B on x.Bar equals y.Bar into z
from y in z.DefaultIfEmpty()
where y == null
select x;
Check the emitted SQL...
I am not too sure if the city filtering is what you are after however the following should achieve what you desire:
var visitsToCity = _db.Visits.Where(v => v.City.Id == city);
var usersOfCity = _db.Users.Where(u => u.City.Id == city);
var nonVisitingUsers = usersOfCity.Where(u => !visitsToCity.Any(v => v.VisitedBy == u));
The last Where combined with the Any should result in a SQL statement like:
SELECT * FROM Users u WHERE u.CityId = #p0 AND
NOT EXISTS(SELECT 1 FROM Visits v WHERE v.CityId = #p0 AND
v.VisitedById = u.Id)
Where #p0 will be supplied with the value of city.

Convert to LINQ lambda expression

Simple line:
var x = (from a in arr select a).First();
Console.WriteLine(“First" + x);
How to convert to Lambda expression?
So you want to convert the LINQ query from using query syntax to plain extension method calls?
// var first = (from a in arr select a).First();
var first = arr.First();
// var last = (from a in arr select a).Last();
var last = arr.Last();
// var filtered = (from a in arr where a == 10 select a).First();
// there are a couple of ways to write this:
var filtered1 = arr.Where(a => a == 10)
.First();
var filtered2 = arr.First(a => a == 10); // produces the same result but obtained differently
// now a very complex query (leaving out the type details)
// var query = from a in arr1
// join b in arr2 on a.SomeValue equals b.AnotherValue
// group new { a.Name, Value = a.SomeValue, b.Date }
// by new { a.Name, a.Group } into g
// orderby g.Key.Name, g.Key.Group descending
// select new { g.Key.Name, Count = g.Count() };
var query = arr1.Join(arr2,
a => a.SomeValue,
b => b.AnotherValue,
(a, b) => new { a, b })
.GroupBy(x => new { x.a.Name, x.a.Group },
x => new { x.a.Name, Value = x.a.SomeValue, x.b.Date })
.OrderBy(g => g.Key.Name)
.ThenByDescending(g => g.Key.Group)
.Select(g => new { g.Key.Name, Count = g.Count() });
When you have an expression of the form (from y in x select y), you can almost always write x instead.

Categories

Resources