How to convert the following sql to lambda expression? - c#

for the following query can anyone please help me convert to lambda expression
SELECT p.partno,
sp.property,
count(s.serialNo) AS PropertyCount
FROM events e
JOIN Products p ON p.productguid = e.productguid
JOIN eventtypes et ON et.eventtypeguid = e.eventtypeguid
JOIN serialcontainerevent sce ON sce.EventGUID = e.EventGUID
JOIN serials s ON s.serialguid = sce.serialguid
JOIN statuses st ON st.statusguid = s.statusguid
LEFT OUTER JOIN serialproperties sp ON sp.serialguid = s.serialguid
WHERE p.partno = '21101'
AND st.code = 'NOTRECEIVED'
AND e.Field1Value = '21101'
AND e.Field2Value = '21101'
AND e.Field3Value = '21101'
AND e.Field4Value = '21101'
AND e.Field5Value = '21101'
AND sp.property = 'Delivery Date' --group by p.partno,s.serialno
GROUP BY p.partno,
sp.property

I think something as follows should get you started. Mind that you may need to optimize it depending on your actual data and relationships:
events
.Where(#event => #event.Field1Value == "21101" && #event.Field2Value == "21101" && #event.Field3Value == "21101" && #event.Field4Value == "21101" && #event.Field5Value == "21101")
.Join(products.Where(product => product.partno == "21101"), #event => #event.productguid, product => product.productguid, (#event, product) => new { #event, product })
.Join(eventtypes, y => y.#event.eventtypeguid, eventType => eventType.eventtypeguid, (y, eventType) => new { y, eventType })
.Join(serialcontainerevent, x => x.y.#event.EventGUID, serialContainerEvent => serialContainerEvent.EventGUID, (x, serialContainerEvent) => new { x, serialContainerEvent })
.Join(serials, w => w.serialContainerEvent.serialguid, serial => serial.serialguid, (w, serial) => new { w, serial })
.Join(statuses.Where(status => status.code == "NOTRECEIVED"), v => v.serial.statusguid, status => status.statusguid, (v, status) => new { v, status })
.GroupJoin(serialproperties.Where(serialProperty => serialProperty.property == "Delivery Date"), u => u.v.serial.serialguid, serialProperty => serialProperty.serialguid, (u, serialProperties) => new { u, serialProperties })
.SelectMany(t => t.serialProperties.Select(s => new { key = new { t.u.v.w.x.y.product.partno, s.property }, t }))
.GroupBy(r => r.key)
.Select(z => new { z.Key.partno, z.Key.property, PropertyCount = z.Where(q => q.t.u.v.serial.serialNo != null).Count() });

Related

C# Linq compress join query with where clause

Hi I am using below code to fetch required data from 2 tables using linq syntax which is working fine.
var ratings = from r in _ratingRepository.AsQueryable()
join c in _convRepository.AsQueryable()
on r.SessionId equals c.CurrentConversationSid
where!c.IsDeleted && c.DateCreated >= request.From && c.DateCreated <=
request.To && c.HasRated
select new Rating() {
Id = r.Id,
SessionId = r.SessionId,
Questions = r.Questions,
AvgRatingValue = r.AvgRatingValue
};
I want to transform this code using below syntax
IQueryable<Rating> ratingsObj = _ratingRepository.AsQueryable()
.Join(_convRepository.AsQueryable().Where(a => a.HasRated), r => r.SessionId, c => c.CurrentConversationSid, (r, c) =>
new Rating()
{
Id = r.Id,
SessionId = r.SessionId,
Questions = r.Questions,
AvgRatingValue = r.AvgRatingValue
});
Its gives below error
System.ArgumentException: 'Expression of type
'System.Collections.Generic.IEnumerable1[Flecx.Chat.Entities.Conversation]' cannot be used for parameter of type 'System.Linq.IQueryable1[Flecx.Chat.Entities.Conversation]' of method
'System.Linq.IQueryable1[Flecx.Chat.Entities.Conversation] Where[Conversation](System.Linq.IQueryable1[Flecx.Chat.Entities.Conversation],
System.Linq.Expressions.Expression1[System.Func2[Flecx.Chat.Entities.Conversation,System.Boolean]])'
(Parameter 'arg0')'
If I remove this code .Where(a => a.HasRated) it runs fine. How can I include the where clause in above syntax.
Need help
try this:
var ratingsObj = _ratingRepository.AsQueryable()
.Join(_convRepository.AsQueryable(),
r => r.SessionId,
c => c.CurrentConversationSid,
(r,c)=>new {r,c}) //**
.Where(a => a.c.HasRated)
.Select(x => new Rating()
{
Id = x.r.Id,
SessionId = x.r.SessionId,
Questions = x.r.Questions,
AvgRatingValue = x.r.AvgRatingValue
});
you can filter anything you want in line with '//**' same below:
(r, c) => new
{ r.Id,
r.SessionId,
r.Questions,
r.AvgRatingValue,
c.HasRated
}
then your code is changed to this:
var ratingsObj = _ratingRepository.AsQueryable()
.Join(_convRepository.AsQueryable(),
r => r.SessionId,
c => c.CurrentConversationSid,
(r, c) => new
{ r.Id,
r.SessionId,
r.Questions,
r.AvgRatingValue,
c.HasRated})
.Where(a => a.HasRated)
.Select(x => new Rating()
{
Id = x.Id,
SessionId = x.SessionId,
Questions = x.Questions,
AvgRatingValue = x.AvgRatingValue
});

Linq-to-SQL query (AsEnumerable) on multiple tables

Here's a Linq-to-SQL query that uses only one table from my SQL Server database and works perfectly:
private void GetData()
{
DateTime d = DateTime.Now;
using (DataClasses1DataContext dc = new DataClasses1DataContext())
{
var qte = dc.ENTREES_STOCKS.AsEnumerable()
.Where(x => x.ENTSTK_LOT == lot)
.Where(x => x.ART_CODE == artCode)
.Where(x => x.ENTSTK_USER == null)
.Select(s => new
{
art = s.ART_CODE,
date = s.ENTSTK_DTENTREE,
numLot = s.ENTSTK_LOT,
pnet = s.ENTSTK_PNET,
nbu = s.ENTSTK_NBU
})
.GroupBy(g => new { g.art, g.date, g.numLot })
.Select(n => new
{
n.Key.art,
n.Key.date,
n.Key.numLot,
pnet = n.Sum(x => Math.Round(Convert.ToDecimal(x.pnet), 2)),
nbu = n.Sum(x => Math.Round(Convert.ToDecimal(x.nbu), 2)),
});
QEntreeTB.Text = qte.First().pnet.ToString();
NbuEntreeTB.Text = qte.First().nbu.ToString();
}
}
How could I modify this code to join other tables to this query like :
private void GetData()
{
DateTime d = DateTime.Now;
using (DataClasses1DataContext dc = new DataClasses1DataContext())
{
var qte = dc.ENTREES_STOCKS.AsEnumerable()
// Thoseline of codes of course doesn't work
join art in dc.FICHES_ARTICLES on ENTREES_STOCKS.ART_CODE equals art.ART_CODE
join ent in dc.STK_ENT on art.ART_CODE equals ent.ART_CODE
....
//
.Where(x => x.ENTSTK_LOT == lot)
.Where(x => x.ART_CODE == artCode)
.Where(x => x.ENTSTK_USER == null)
.Select(s =>
new
{
art = s.ART_CODE,
date = s.ENTSTK_DTENTREE,
numLot = s.ENTSTK_LOT,
pnet = s.ENTSTK_PNET,
nbu = s.ENTSTK_NBU
}
)
.GroupBy(g => new { g.art, g.date, g.numLot })
.Select(n =>
new
{
n.Key.art,
n.Key.date,
n.Key.numLot,
pnet = n.Sum(x => Math.Round(Convert.ToDecimal(x.pnet), 2)),
nbu = n.Sum(x => Math.Round(Convert.ToDecimal(x.nbu), 2)),
}
);
QEntreeTB.Text = qte.First().pnet.ToString();
NbuEntreeTB.Text = qte.First().nbu.ToString();
}
}
Or is there à way to code this query another way ??
Because in fact i just want to join multiples tables, groupby some fields and sum others fields.
Firstly, calling AsEnumerable is a bit redundent. Then you can simply use the Join extension method.
var qte = dc.ENTREES_STOCKS
.JOIN(dc.FICHES_ARTICLES,art=>art.ART_CODE, stock => stock.ART_CODE)
.JOIN(dc.STK_ENT,ent => ent.ART_CODE,stock => stock.ART_CODE)
.Where(x => x.ENTSTK_LOT == lot)
.Where(x => x.ART_CODE == artCode)
.Where(x => x.ENTSTK_USER == null)
....
You can find more answers here:
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/method-based-query-syntax-examples-join-operators

how to translate linq groupjoin to lambda groupjoin

Because i need to do some filter condition feature ,I'm now want to translate a linq query to the lambda expression object.
linq code:
var query = from chlsynclog in oaPtDbContext.TableChlSyncLog
join mealchl in oaPtDbContext.TableMealChl on new { X1 = chlsynclog.Mealid, Y1 = chlsynclog.Chid } equals new { X1 = mealchl.Mealid, Y1 = mealchl.Chid }
into mealchlGroup
from mealchlGroupItem in mealchlGroup.DefaultIfEmpty()
join service in oaPtDbContext.TableService on mealchlGroupItem.Sid equals service.Sid
into serviceGroup
from serviceGroupItem in serviceGroup.DefaultIfEmpty()
join channel in oaPtDbContext.TableChannel on chlsynclog.Chid equals channel.Chid
into channelGroup
from channelGroupItem in channelGroup.DefaultIfEmpty()
join area in oaPtDbContext.TableArea on chlsynclog.Areaid equals area.Areaid
into areaGroup
from areaGroupItem in areaGroup.DefaultIfEmpty()
select new
{
chlsynclog.Id,
chlsynclog.Handset,
mealchlGroupItem.Mealname,
areaGroupItem.Proname,
areaGroupItem.Cityname,
chlsynclogType= GetChlsynclogType(chlsynclog.Type),
statusName=GetStatusName(chlsynclog.Statusid),
channelGroupItem.Chname,
syncTime=chlsynclog.Synctime.ToString("yyyy-MM-dd HH:mm:ss")
};
and I began to do this work,after i translated to the third
join
var testQuery =
oaPtDbContext.TableChlSyncLog
.GroupJoin(oaPtDbContext.TableMealChl,
(chlsynclog) => new
{
X1 = chlsynclog.Mealid,
X2 = chlsynclog.Chid
},
(mealchl) => new
{
X1 = mealchl.Mealid,
X2 = mealchl.Chid
},
(x, y) => new
{
X = x,
Y = y
})
.SelectMany(temp0 => temp0.Y.DefaultIfEmpty())
.GroupJoin(oaPtDbContext.TableService,
mealchl => mealchl.Sid,
service => service.Sid,
(x, y) => new { X = x, Y = y })
.SelectMany(temp0 => temp0.Y.DefaultIfEmpty())
.GroupJoin(oaPtDbContext.TableChannel,)
;
.GroupJoin(oaPtDbContext.TableChannel,)
The Second parameter just get the previous type's object TableService,
but i need the parameter should be the TableCholSynclog's Chid.
So here I have no idea to go on this work.
And I use the query.Expression.ToString() to see the expression:
<>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.chlsynclog.Chid
The sourcecode can do this but i can not !
So,How to write my lambda expression ????
Are you sure you want lambda?
var query = oaPtDbContext.TableChlSyncLog.GroupJoin(
oaPtDbContext.TableMealChl,
chlsynclog => new
{
X1 = chlsynclog.Mealid,
Y1 = chlsynclog.Chid
},
mealchl => new
{
X1 = mealchl.Mealid,
Y1 = mealchl.Chid
},
(chlsynclog, mealchlGroup) => new
{
chlsynclog,
mealchlGroup
})
.SelectMany(
#t => mealchlGroup.DefaultIfEmpty(),
(#t, mealchlGroupItem) => new
{
#t,
mealchlGroupItem
})
.GroupJoin(
oaPtDbContext.TableService,
#t => mealchlGroupItem.Sid,
service => service.Sid,
(#t, serviceGroup) => new
{
#t,
serviceGroup
})
.SelectMany(
#t => serviceGroup.DefaultIfEmpty(),
(#t, serviceGroupItem) => new
{
#t,
serviceGroupItem
})
.GroupJoin(
oaPtDbContext.TableChannel,
#t => chlsynclog.Chid,
channel => channel.Chid,
(#t, channelGroup) => new
{
#t,
channelGroup
})
.SelectMany(
#t => channelGroup.DefaultIfEmpty(),
(#t, channelGroupItem) => new
{
#t,
channelGroupItem
})
.GroupJoin(
oaPtDbContext.TableArea,
#t => chlsynclog.Areaid,
area => area.Areaid,
(#t, areaGroup) => new
{
#t,
areaGroup
})
.SelectMany(
#t => areaGroup.DefaultIfEmpty(),
(#t, areaGroupItem) => new
{
chlsynclog.Id,
chlsynclog.Handset,
mealchlGroupItem.Mealname,
areaGroupItem.Proname,
areaGroupItem.Cityname,
chlsynclogType = GetChlsynclogType(chlsynclog.Type),
statusName = GetStatusName(chlsynclog.Statusid),
channelGroupItem.Chname,
syncTime = chlsynclog.Synctime.ToString("yyyy-MM-dd HH:mm:ss")
});
Note : This was just Resharpers, Convert Linq to chain method feature. you can probably make this a loooot prettier.

Group By using more than two columns by Lambda expression

I have to convert my given linq query in lambda expression. i.e.
var scholars = (from scholar in db.Scholars
join suspension in db.Suspensions
on scholar.ID equals suspension.ScholarID
where suspension.StartDate >= startDate &&
suspension.EndDate <= endDate
group scholar by new { scholar.ID, scholar.FirstName, scholar.LastName }
into g
select new
{
FullName = g.Key.FirstName +" " + g.Key.LastName,
TotalSuspensionSum = g.Sum(x => x.Suspensions.Sum(y => y.SuspensionDays))
})
.ToList()
.OrderBy(x=> x.FullName);
this is your lambda:
var scholars = db.Scholars.Join(db.Suspensions,
scholar => scholar.ID,
suspension => suspension.ScholarID,
(scholar, suspension) => new {scholar, suspension})
.Where(u => u.suspension.StartDate >= startDate &&
u.suspension.EndDate <= endDate)
.GroupBy(u => new { u.scholar.ID, u.scholar.FirstName, u.scholar.LastName })
.Select(u => new
{
FullName = u.Key.FirstName + " " + u.Key.LastName,
TotalSuspensionSum = u.Sum(x =>
x.scholar.Suspensions.Sum(y => y.SuspensionDays)
)
})
.OrderBy(x => x.FullName)
.ToList();
Well I don't think I should do all your work for you but specifically the group by you are asking about could be done like:
...GroupBy(x => new { x.ID, x.FirstName, x.LastName })...

Helpme to Convert from SQL to linq Nested lambda Expression with EntityFramework

I´m trying to bring some Data from SQL but I cant do it with Linq, in T-SQL this Work:
select *
from MTRBatch MB
Inner Join MTR M on MB.Id = M.MTRBatchId
Inner JOIN MTRHeats MH on M.Id = MH.MTRId
LEFT OUTER JOIN Vendor V on MB.VendorId = v.Id
Inner Join Manufacturer MF on MB.ManufacturerId = MF.Id
Where MB.ManufacturerId = 1
AND MH.Heat = 'z01'
I need All the tree but with that filter.
I try this but didnt work :
MTRBatches
.Include(x => x.MTRs.Select(m => m.MTRHeats))
.Include(x => x.Manufacturer)
.Include(x => x.Vendor)
.Where(x => (x.Manufacturer.Id == 1));
.Where(x => x.MTRs.Any(m => m.MTRHeats.Any(h => h.Heat == 'z01')));
This should help; dataContext is the name of your instance of Entity Framework container.
var result = dataContext.MTRBatches
.Join(dataContext.MTRs,
mb => mb.Id,
mtr => mtr.MTRBatchId,
(mb, mtr) => new{ Batch = mb, MTR = mtr })
.Join(dataContext.MTRHeats,
x => x.MTR.Id,
mh => mh.MTRId,
(x, mh) => new{ Batch = x.Batch, MTR = x.MTR, Heat = mh })
.Join(dataContext.Vendors.DefaultIfEmpty(),
x => x.Batch.VendorId,
v => v.Id,
(x, v) => new{ Batch = x.Batch, MTR = x.MTR, Heat = x.Heat, Vendor = v })
.Join(dataContext.Manufacturers,
x => x.Batch.ManufacturerId,
mf => mf.Id,
(x, mf) => new{ Batch = x.Batch, MTR = x.MTR, Heat = x.Heat, Vendor = x.Vendor, Manufacturer = mf})
.Where(x => x.Manufacturer.Id == 1 && x.Heat.Heat == "z01");

Categories

Resources