Linq select statement not working after grouping - c#

I am getting data from multiple tables by joining and I want to group data on basis of date but after group by the statement, I'm getting an error to select all entities against a date.
var query = from record in _entityRepository.GetAll().Where(x => x.DateRecord > DateTime.UtcNow.Date)
join job in _jobRepository.GetAll() on record.Id equals job.Id
into g1
from job in g1.DefaultIfEmpty()
join punchList in _punchListRepository.GetAll() on record.Id equals punchList.Id
into g2 from punchList in g2.DefaultIfEmpty()
join punchJob in _jobRepository.GetAll() on punchList != null ? -1 : punchList.JobId equals punchJob.Id
into g4 from punchJob in g4.DefaultIfEmpty()
group new {record, job, punchList, punchJob} by new{ record.DateRecord}
into g3
select new
{
Date = g3.Key,
job= g3.Select(x=>x.job),
punchList= g3.Select(x=>x.punchList)
};
And I also have tried ToList() in select statement but it did not work.

Try this:
var entityRepository=_entityRepository.GetAll().Where(x => x.DateRecord > DateTime.UtcNow.Date).ToList();
var jobRepository=_jobRepository.GetAll().ToList();;
var punchListRepository=_punchListRepository.GetAll().ToList();;
var query = from record in entityRepository
join job in jobRepository on record.Id equals job.Id into g1
from job in g1.DefaultIfEmpty()
join punchList in punchListRepository on record.Id equals punchList.Id into g2
from punchList in g2.DefaultIfEmpty()
join punchJob in jobRepository on punchList != null ? -1 : punchList.JobId equals punchJob.Id into g4
from punchJob in g4.DefaultIfEmpty()
group new {record, job, punchList, punchJob} by new{ record.DateRecord} into g3
select new
{
Date = g3.Key,
job= g3.Select(x=>x.job).ToList(),
punchList= g3.Select(x=>x.punchList).ToList()
};

We need to split the query into two parts because group by clause is not fully converted into SQL so in my case I want one-month data so below is my code snipet.
var query = from record in _entityRepository.GetAll().Where(x =>
x.DateRecord > DateTime.UtcNow.Date && x.DateRecord <= DateTime.UtcNow.Date.AddMonths(1))
join job in _jobRepository.GetAll() on record.Id equals job.Id
into g1
from job in g1.DefaultIfEmpty()
join punchList in _punchListRepository.GetAll() on record.Id equals punchList.Id
into g2
from punchList in g2.DefaultIfEmpty()
join punchJob in _jobRepository.GetAll() on punchList != null ? -1 : punchList.JobId equals punchJob.Id
into g4
from punchJob in g4.DefaultIfEmpty()
select new {record, job, punchList,punchJob};
var queryResult = await query.ToListAsync();
var result = queryResult.GroupBy(x => x.record.DateRecord)
.Select(o => new
{
Date = o.Key,
job = o.Select(x => x.job ?? new Job()).ToList(),
punchList = o.Select(x => x.punchList ?? new PunchList()).ToList()
});

Related

Multiple Left Join with Linq and Defaults Values

I'm trying to write a query that contains multiple left joins in linq in a c# .netcore 2.2 application. I've tried writing the query in linq but it is not properly retrieving all the rows. Query I'm trying to convert is as follows.
select ISNULL(b.Id, '00000000-0000-0000-0000-000000000000') as 'Bat Id', p.Id as 'ProductId', p.RP, u.UnitName as 'UnitName', ISNULL(b.QTY,0) as 'BusQty', p.[Name] as 'Product Name'
from Products p left join Bat b
ON p.Id = b.ProductId
left join Units u on p.UOId = u.Id;
linq I have so far
var allProducts = (from p in _db.Products
join s in _db.Bat on p.Id equals s.ProductId into ps
from s in ps.DefaultIfEmpty()
join u in _db.Units on p.UOId equals u.Id
select new
{
BatId = s.Id == null ? Guid.NewGuid() : s.Id,
RP = p.RP,
BusQty = s.QTY == null ? 0 : s.QTY,
ProductName = p.Name,
UnitName = u.UnitName,
ProductId = p.Id,
}).ToList();
You are missing DefaultIfEmpty() on Units, thereby turning it into an inner join
var allProducts = (
from p in _db.Products
join s in _db.Bat on p.Id equals s.ProductId into ps
from s in ps.DefaultIfEmpty()
join u in _db.Units on p.UOId equals u.Id into us
from u in us.DefaultIfEmpty()
select new
{
BatId = s.Id ?? Guid.NewGuid(),
RP = p.RP,
BusQty = s.QTY ?? 0,
ProductName = p.Name,
UnitName = u.UnitName,
ProductId = p.Id,
}).ToList();

T-SQL to LINQ query that has a case statement and a subquery in it

I'm a complete beginner in LINQ and I would like to convert this T-SQL query in LINQ
SELECT
CASE
WHEN D.IsBaseloadDefined = 1
THEN COUNT(D.DeviceID)
ELSE
(SELECT COUNT(DORG.DeviceID)
FROM DeviceOrganization DORG
INNER JOIN Organization ORG ON DORG.OrganizationID = ORG.OrganizationID
INNER JOIN BaseloadOrganization BO ON ORG.BaseloadOrganizationId = BO.OrganizationID
INNER JOIN Baseload BL ON BO.BaseloadID = BL.BaseloadID
WHERE DORG.DeviceID = D.DeviceID
AND BL.RecursUntil >= GETDATE()
GROUP BY DORG.DeviceID)
END AS [Nb of devices]
FROM DeviceOrganization DO
INNER JOIN Device D ON DO.DeviceID = D.DeviceID
LEFT JOIN BaseloadDevice BD ON D.DeviceID = BD.DeviceID
LEFT JOIN Baseload B ON BD.BaseloadID = B.BaseloadID AND B.RecursUntil >= GETDATE()
INNER JOIN OrganizationHierarchy OH ON DO.OrganizationID = OH.SubOrganizationID
WHERE OH.OrganizationID = 6
AND D.IsActive = 1
group by D.DeviceID, D.IsBaseloadDefined
I've seen this topic but I don't really understand the answer
The only thing I could do so far is this, and now I'm completly lost
from deviceO in _context.DeviceOrganizations
join d in _context.Devices on deviceO.DeviceID equals d.DeviceID
join bd in _context.BaseloadDevices on d.DeviceID equals bd.DeviceID
join b in _context.Baseloads on bd.BaseloadID equals b.BaseloadID
join oh in _context.OrganizationHierarchies on deviceO.OrganizationID equals oh.SubOrganizationID
where oh.OrganizationID == OrganizationId
where d.IsActive == true
where b.RecursUntil <= DateTime.Now
group d.DeviceID by d.DeviceID).Count()
Instead of get count of group
group d.DeviceID by d.DeviceID).Count()
you should save result in variable
var data = from deviceO in _context.DeviceOrganizations
join d in _context.Devices on deviceO.DeviceID equals d.DeviceID
join bd in _context.BaseloadDevices on d.DeviceID equals bd.DeviceID
join b in _context.Baseloads on bd.BaseloadID equals b.BaseloadID
join oh in _context.OrganizationHierarchies on deviceO.OrganizationID equals oh.SubOrganizationID
where oh.OrganizationID == OrganizationId
where d.IsActive == true
where b.RecursUntil <= DateTime.Now
and then you should do something like this:
//group by 2 properties
var result = data.GroupBy(d => new { d.DeviceID, d.IsBaseloadDefined })
.Select(g =>
{
//for each group we get IsBaseloadDefined property
var IsBaseloadDefined = g.Key.IsBaseloadDefined;
if (IsBaseloadDefined == 1)
{
return g.Count();
}
else
{
// here another select that return count:
//(SELECT COUNT(DORG.DeviceID)
//FROM DeviceOrganization DORG
// INNER JOIN Organization ORG ON DORG.OrganizationID = ORG.OrganizationID
//INNER JOIN BaseloadOrganization BO ON ORG.BaseloadOrganizationId = BO.OrganizationID
//INNER JOIN Baseload BL ON BO.BaseloadID = BL.BaseloadID
//WHERE DORG.DeviceID = D.DeviceID
//AND BL.RecursUntil >= GETDATE()
//GROUP BY DORG.DeviceID)
//in this query you should return Count() of group
return 1; //return group.Count() instead 1
}
});
I hope this helps you

How can i join two table in Linq and display the join to Data GridView?

I'm trying to join two tables and to display the Join result into GridView in WinForms, but something is going wrong...
it's not giving me Error message or something, Please help!!
my code :
var temp = teacherCmbBx.SelectedItem.ToString();
var temp2 = (from c in context.Teachers
where temp == c.FirstName
select c).ToList();
long num = temp2[0].ID;
var teacherGroup = (from t in context.Teachers
join g in context.Groups on t.ID equals g.TeacherID
where num == t.ID
select t);
teachergrpGridView.DataSource = teacherGroup;
string temp3 = (string)teachergrpGridView.Rows[rowNum].Cells[0].Value;
You are almost there. You are just missing .ToList()
var teacherGroup = (from t in context.Teachers
join g in context.Groups on t.ID equals g.TeacherID
where num == t.ID
select t).ToList();
teachergrpGridView.DataSource = teacherGroup;
var teacherGroup = from t in context.Teachers
join g in context.Groups on t.ID equals g.TeacherID
where num == t.ID
select new {
t.Id ,
g.Name,
t.xxxx
};

Linq to entities query with nested query on the same table

I have a SQL query:
SELECT distinct A.stock_value_site,
A.BALANCE_QUANTITY,
A.BALANCE_NOMINAL_VALUE,
A.BALANCE_INDEXED_VALUE,
V.STOCK_VALUE_ORDER,
U.BALANCE_QUANTITY
FROM svr A,
svt V,
svu U
WHERE V.Code = 500 and
A.Id = U.ID (+) and
A.Id = (SELECT max(B.id)
FROM svr B,
sts
WHERE A.stock_value_site = B.stock_value_site and
B.Id = sts.ID(+) and
B.item = _item and
B.date < _from_date and
B.Id IS NULL)
I tried to convert this query to Linq to entities:
var data = (from A in _context.svr
join V in _context.svt on A.svtId equals V.Code
join U in _context.svu on A.Id equals U.Id into groupA
from gA in groupA.DefaultIfEmpty()
where V.Code == _openBalanceRecordId &&
A.Id == (from B in _context.svr
join st in _context.sts on B.Id equals st.Id into groupB
from gB in groupB.DefaultIfEmpty()
where A.svsId == B.svsId &&
B.ItemId == _item &&
B.Date < _startDate.Date
select B.Id).Max()
select new
{
A.stock_value_site,
A.BALANCE_QUANTITY,
A.BALANCE_NOMINAL_VALUE,
A.BALANCE_INDEXED_VALUE,
V.STOCK_VALUE_ORDER,
gA == null ? 0 : gA.BALANCE_QUANTITY
}).Distinct().ToList();
When I run the SQL query in oracle I get 33 records back. But when I run it using Linq to entities I don't get any record.
What am I doing wrong?
I believe there are still some issues with you're original query, if I understand what you're trying to do, this should work better:
var results =
(from a in _context.svr
from v in _context.svt.Where(t => t.Code == 500)
join u in _context.svu on u.Id equals a.Id into gU
from x in gU.DefaultIfEmpty()
where a.Id ==
(from b in _context.svr
join s in _context.sts on b.Id equals s.Id
where b.item = _item
and b.date < _from_date
and b.svsId == a.svsId
select b.Id).Max()
select new
{
a.stock_value_site,
a.BALANCE_QUANTITY,
a.BALANCE_NOMINAL_VALUE,
a.BALANCE_INDEXED_VALUE,
v.STOCK_VALUE_ORDER,
x == null ? 0 : x.BALANCE_QUANTITY
}).Distinct().ToList();
Or possibly this:
var results =
(from a in _context.svr
from v in _context.svt.Where(t => t.Code == 500)
join u in _context.svu on u.Id equals a.Id into gU
from x in gU.DefaultIfEmpty()
let subQuery =
(from b in _context.svr
join s in _context.sts on b.Id equals s.Id
where b.item = _item
and b.date < _from_date
select new { b.Id, b.svsId })
join y in subQuery on a.svsId equals y.svsId into gY
where a.Id = y.Max(b => b.Id)
select new
{
a.stock_value_site,
a.BALANCE_QUANTITY,
a.BALANCE_NOMINAL_VALUE,
a.BALANCE_INDEXED_VALUE,
v.STOCK_VALUE_ORDER,
x == null ? 0 : x.BALANCE_QUANTITY
}).Distinct().ToList();

Convert special SQL query to Linq

do you know how write this SQL Query to linq ?
SELECT *
FROM
a
INNER JOIN b
ON a.FkSubmissionId = b.Id
RIGHT JOIN c
ON a.FkItemId = c.Id
WHERE
(b.FkUserId = '...' OR b.FkUserId is null)
and
(c.FkTenderId = 2)
I use Linquer and the best I have from the tool is that :
Linq :
from
items in _context.Items
from
si in _context.si
join s in _context.s
on new { fki = si.fki } equals new { fki = s.Id }
into
submissions_join
from
s in submissions_join.DefaultIfEmpty()
...
Result in SQL :
SELECT *
FROM
[Items] AS [t0]
CROSS JOIN [SubmissionsItems] AS [t1]
LEFT OUTER JOIN [Submissions] AS [t2]
ON [t1].[FkSubmissionId] = [t2].[Id]
WHERE
(([t2].[FkUserId] = #p0) OR (([t2].[FkUserId]) IS NULL))
AND
([t0].[FkTenderId] = #p1)
So the final result it not what I get from the query I need...
Thank you for your help !!!
Try this:
var part1 =
from x in a
join y in b on x.FkSubmissionId equals y.Id
where b.FkUserId = "..."
select new {x, y};
var part2 =
from c in z
where c.FkTenderId == 2
join xy in part1
on z.Id equals xy.x.FkItemId
into xys
from xy in xys.DefaultIfEmpty()
select new {xy.x, xy.y, z};
I would reorder your query so you can use a left join instead of a right join
var query = from c in context.C
from a in context.A.Where(x => c.Id == x.FkItemId)
.DefaultIfEmpty()
join b in context.B on a.FkSubmissionId equals b.id
where b.FkUserId == '...' || b.FkUserId == null
where c.FkTenderId == 2
select new {
a,
b,
c
};

Categories