How to Create the Left Join by using the group by data - c#

I have three Table One is "Allowance " ,"Balance" and "TimeoffRequests" in these three table common columns are EmployeeId and TimeoffTypeId, Now i need to get the requested hours of one leave type by grouping thier timeoffTypeId and EmployeeId from the table "TimeoffRequests" , and got the "TimeOffHours". for the i wrote the code like
var query = (from tr in TimeOffRequests
where tr.EmployeeID == 9
group tr by new { tr.EmployeeID, tr.TimeOffTypeID } into res
select new
{
EmployeeID = res.Key.EmployeeID,
TimeOffTypeID = res.Key.TimeOffTypeID,
TotalHours = res.Sum(x => x.TimeOffHours)
}).AsEnumerable();
Now I need to join these results with the first table and have to get the all the employees, and timeoffTypes from the UserAllowance and corresponding TimeoffHours from the grouped table. for getting left joined query i wrote like below.
var requestResult = (from UA in UserAllowances
join UB in UserBalances on UA.EmployeeID equals UB.EmployeeID
where UA.TimeOffTypeID == UB.TimeOffTypeID && UA.EmployeeID == 9
&& UA.TimeOffType.IsDeductableType == true // LeftJoin
join rest in query on UA.EmployeeID equals rest.EmployeeID into penidngRequst
from penReq in penidngRequst.DefaultIfEmpty()
where penReq.TimeOffTypeID == UA.TimeOffTypeID
select new EmployeeTimeOffBalanceModel
{
TimeOffTypeID = UA.TimeOffTypeID != null ? UA.TimeOffTypeID : 0,
YearlyAllowanceHrs = (UA.YearlyAllowanceHrs != null) ? UA.YearlyAllowanceHrs : 0,
BalanceHours = UB.BalanceHrs != null ? UB.BalanceHrs : 0,
PendingHours = (decimal)((penReq != null) ? (penReq.TotalHours) : 0),
EmployeeID = UA != null ? UA.EmployeeID : 0,
}).ToList().Distinct();
It is giving only timeOFfType containing in grouped data,even though I wrote leftjoin for the query using the "into" and DefaultIfEmpty() keywords. the results becomes as like:
and by using the "linqPad" editor i found that it is applying the Cross or Outer Join instead of "left join" what will be the reason.
If I remove this line of code " where penReq.TimeOffTypeID
== UA.TimeOffTypeID" this showing all the timeoffTypes with cross join with repeatation like
How can I achieve left join with tables with Grouped data and showing null values if timeofftypes didn't having the any request?

You might want to move the where clause into the the on equals clause as shown below
join rest in query on new { UA.EmployeeID, UA.TimeOffTypeID } equals new { rest.EmployeeID, rest.TimeOffTypeID } into penidngRequst
from penReq in penidngRequst.DefaultIfEmpty()

You can change
where penReq.TimeOffTypeID == UA.TimeOffTypeID
to
where penReq == null || penReq.TimeOffTypeID == UA.TimeOffTypeID

Related

Can't convert stored procedure to Linq expression successfully

How can I convert this SQL Server stored procedure to a linq expression? I've got a couple of mistakes but don't know how to fix them.
Here is the stored procedure:
#MatterNumber NVARCHAR(20)
AS
DECLARE #ClientNumber INT = (SELECT TOP 1 LeadPlaintiffNumber
FROM [dbo].[vw_cmp_case_numbers]
WHERE MatterNumber = #MatterNumber)
SELECT DISTINCT
defendantid,
defendantcode,
defendantname DefendantName
FROM
(SELECT DISTINCT
fmrp.employerid DefendantId,
fmrp.employercode DefendantCode,
fmrp.employername DefendantName
FROM
vw_mpid_records fmr
LEFT JOIN
vw_mpid_records_products fmrp ON fmr.recordid = fmrp.recordid
INNER JOIN
vw_cmp_event_history fceh ON fmr.jobsitecode = fceh.jobsitecode
AND fmr.startdate < = fceh.enddate
WHERE
fceh.clientnumber = #ClientNumber
AND fmrp.employerid IS NOT NULL
AND fmrp.employercode IS NOT NULL
GROUP BY
fmrp.employerid, fmrp.employercode, fmrp.employername) yyy
ORDER BY
defendantname
Here is what I have so far for the linq but there is a error at
fmr.StartDate <= fceh.EndDate
and then I'm not sure about the group by as well
var #clientNumber = (from ccn in context.VwCmpCaseNumbers where ccn.MatterNumber == text select ccn).Take(1);
var innerQuery = from fmr in context.VwMpidRecords
join fmrp in context.VwMpidRecordsProducts on fmr.Id equals fmrp.Id
into gj
from x in gj.DefaultIfEmpty()
join fceh in context.VwCmpEventHistorys on fmr.JobsiteCode equals fceh.JobsiteCode && fmr.StartDate <= fceh.EndDate
where fceh.ClientNumber = #clientNumber &&
fmrp.EmployerID != null &&
fmrp.EmployerCode != null
group fmrp.by fmrp.EmployerID && fmrp.EmployerCode && fmrp.EmployerName
var outerQuery = (from r in innerQuery
select new
{
EmployerId = r.EmployerID,
EmployerCode = r.EmployerCode,
EmployerName = r.EmployerName
}).OrderBy(obj => obj.DefendantName);
var viewModel = outerQuery.Select(obj => new SelectOption
{
Text = obj.DefendantCode,
Value = obj.DefendantId,
});
Here are the lines that show the errors
LINQ doesn't allow you to "join" on any criteria you want: a join can only have a [this] equals [that] form. Move any criteria that doesn't match that pattern into a where clause. (This will not impact performance of the SQL query.)
Also, group by values need to be contained in a single (anonymous) object, not &&ed together.
var innerQuery = from fmr in context.VwMpidRecords
join fmrp in context.VwMpidRecordsProducts
on fmr.Id equals fmrp.Id
join fceh in context.VwCmpEventHistorys
on fmr.JobsiteCode equals fceh.JobsiteCode
where fmr.StartDate <= fceh.EndDate
where fceh.ClientNumber = #clientNumber
where fmrp.EmployerID != null && fmrp.EmployerCode != null
group fmrp by new {fmrp.EmployerID, fmrp.EmployerCode, fmrp.EmployerName};

C# Linq Left Outer Join WHERE clause

I have a linq query where i'm trying to return data if the right Sales table doesn't have a record and also only if the Sales.Fallthrough == false && Sales.Date == null.
This is the base of my query and i've tried many different things with this but can't seem to get it to return the required data. Everything I try only seems to return records if there is no Sales OR they match the WERE caluse but not both.
from cr in efContext.Cases
join si in efContext.Sales on cr.CaseId equals si.CaseId into sicr
from sicr in (from si in sicr
where si == null
select si
).DefaultIfEmpty()
where cr.Withdrawn == false
select new
{
CaseId = cr.CaseId,
PropertyAddress = extension.PropertyAddressTownFormat(cr.PropertyAddress1, cr.PropertyTown),
TargetExchangeDate = sicr.TargetExchangeDate == null ? null : sicr1.TargetExchangeDate,
ActualExchangeDate = sicr.ActualExchangeDate,
}).ToList();
EDIT
Missed out a little information.
Also if there is a record in Sales but does not match WHERE clauses then still return the left side and the right side as if there wasn't a record.
Thanks.
Isn't it just...?
from cr in efContext.Cases
join si in efContext.Sales on cr.CaseId equals si.CaseId into sicr
from s in sicr.DefaultIfEmpty()
select new
{
CaseId = cr.CaseId,
PropertyAddress = extension.PropertyAddressTownFormat(cr.PropertyAddress1, cr.PropertyTown),
TargetExchangeDate = s == null || (s.Fallthrough == false && s.Date == null) ? null : s.TargetExchangeDate,
ActualExchangeDate = s == null || (s.Fallthrough == false && s.Date == null) ? null : s.ActualExchangeDate,
};
Please note that you cannot call to ToList since the query returns an anonymous type.

C# Linq statement to join two tables and multiple columns

I have two tables; EndToEnd and PartPort. I'd like to get the PartPortA and PartportB data from the same row in EndToEnd, and query Partport with them and get their corresponding PartGid from Partport which could be on any row in the Partport table. So far, I'm able to do this, but I have to do two different LINQ calls but I'd like to reduce it down to one. Here is my code:
// this demonstrates how to join two tables, however only works for one AssetportGid at a time
var part_portGid_a_results = (from icp in entities.EndToEnd
where icp.IntertPortGidA != null &&
icp.IntertPortGidB != null
join ica in entities.PartPort
on icp.PartPortA equals ica.PortGid
select new { icp.PartPortA, ica.PartGid, }).ToList();
var part_portGid_b_results = (from icp in entities.EndToEnd
where icp.IntertPortGidA != null &&
icp.IntertPortGidB != null
join ica in entities.PartPort
on icp.PartPortB equals ica.PortGid
select new { icp.PartPortA, ica.PartGid, }).ToList();
return Json(part_portGid_a_results, JsonRequestBehavior.AllowGet);
What i'd like to do, and I have already tried but got an error is this:
var part_portGid_a_results = (from icp in entities.EndToEnd
where icp.IntertPortGidA != null &&
icp.IntertPortGidB != null
join ica in entities.PartPort
on icp.PartPortA && icp.PartPortB equals ica.PortGid
select new { icp.PartPortA, ica.PartGid, }).ToList();
The error i get is:
Guid? EndToEnd.PartPortB
Error:
Operator '&&' cannot be applied to operands of type 'System.Guid' and 'System.Guid?'
You don't have to use join. If you want to join with a "complex" comparison, just make a Cartesian product (from ... from) and link the rows by a where clause
var part_portGid_results = (from icp in entities.EndToEnd
where icp.IntertPortGidA != null &&
icp.IntertPortGidB != null
from ica in entities.PartPort
where icp.PartPortA == ica.PortGid
|| icp.PartPortB == ica.PortGid
select new { icp.PartPortA, ica.PartGid, }).ToList();

How to convert multiple SQL LEFT JOIN statement with where clause to LINQ

Is there any way to convert following SQL statement into LINQ?
select ve.EntityID
, fin1.FinanceStat as FinanceStat_New
, fin2.FinanceStat as FinanceStat_Old
from ValuationEvents_PIT_New as ve
left join FinStat_New as Fin1
on ve.EntityID = Fin1.EntityID
left join FinStat_Old as Fin2
on ve.EntityID = Fin2.EntityID
where Fin1.FinanceStat ne Fin2.FinanceStat
and Fin2.FinanceStat is not null
and charindex(Fin1.FinanceStat, 'abc') < 1
and charindex(Fin1.FinanceStat, 'xyz') < 1
Here is my version of it, but I need extra pair of eyes to look at it.
var result = (from ve in valuationEventsPit
join fsn in finStatNew on ve.EntityId equals fsn.EntityID into veFsn
from fin1 in veFsn.DefaultIfEmpty()
join fso in finStatOld on ve.EntityId equals fso.EntityID into veFso
from fin2 in veFso.DefaultIfEmpty()
select new
{
ve.EntityId,
FinStatNew1 = fin1 == null ? null : fin1.FinanceStat,
FinStatNew2 = fin2 == null ? null : fin2.FinanceStat
}).
Where(x => x.FinStatNew1 != null &&
x.FinStatNew2 != null &&
x.FinStatNew1 != x.FinStatNew2 &&
!(x.FinStatNew1.Contains("abc")) &&
!(x.FinStatNew1.Contains("xyz"))).ToList();
The reason I am excluding x.FinStatNew1 == null because of the charindex(Fin1.FinanceStat, 'abc') < 1, which will always return 0 if x.FinStatNew1 is not null and 'abc' or 'xyz' is not there and if x.FinStatNew1 is null then it will return null and condition still will be false (null < 0).
Thanks a lot for your help.
I think you could reduce that query even more and rearrange some things to make it more readable. Based on the original query and these are actually LINQ to objects queries, I'd try this:
const string con1 = "abc";
const string con2 = "xyz";
var query =
from ve in valuationEventPit
join fsn in finStatNew on ve.EntityId equals fsn.EntityID
join fso in finStatOld on ve.EntityId equals fso.EntityID
let FinStatNew = fsn.FinanceStat
let FinStatOld = fso.FinanceStat
where FinStatNew != FinStatOld && FinStatOld != null
&& new[]{con1,con2}.All(con => !FinStatNew.Contains(con))
select new { ve.EntityId, FinStatNew, FinStatOld };
The left join is not necessary here. Since you exclude the null values, we could just ignore them then and do the inner join.

Need help populating an asp:dropdownlist from multiple tables in an SQL database

I have 4 tables: CustomerDocument, CustomerLink, CustomerAdditionalInfo, and CustomerImage. They each have a value of CustomerNumber, and I need to way to pull the customer numbers from each table and put in a drop down list. I know how to do it with one table, but not multiple. Also, there is a restriction that the CustomerNumber needs to be not null, so do I need to include this with each join? Here is a bit of code I have now. oDb is the DataContext
var oData = from c in oDb.CustomerAdditionalInfos
where ( c.CustomerID == CustomerID &&
c.CustomerNumber != null &&
c.CategoryID == CategoryID )
orderby c.CustomerNumber
select new { c.CustomerNumber };
return oData;
You could do this....
var oData = (from c in oDb.CustomerAdditionalInfos
where c.CustomerNumber != null
select new
{
CustomerNumber = c.CustomerNumber
}).Union
(from d in oDb.CustomerDocument
where d.CustomerNumber != null
select new
{
CustomerNumber = d.CustomerNumber
}).Union
(from l in oDb.CustomerLink
where l.CustomerNumber != null
select new
{
CustomerNumber = l.CustomerNumber
}).Union
(from i in oDb.CustomerImage
where i.CustomerNumber != null
select new
{
CustomerNumber = i.CustomerNumber
}).OrderBy(c => c.CustomerNumber);
That is simply a union of all of the CustomerNumbers in all four tables. This WILL include duplicates if there are duplicates. If you want only distinct CustomerNumbers, then just do a Distinct() after the OrderBy.

Categories

Resources