Can't convert stored procedure to Linq expression successfully - c#

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

Related

Error: the specified linq expression contains references to queries that are associated with different context

I have this linq query that returns the revenue associated with every colorwaysid present within the given dates but it throws the SQLException:
the specified linq expression contains references to queries that are
associated with different context
using (var eshaktiDb = new eshaktiEntities())
{
using (var corpDb = new eshakti_corpEntities())
{
var queryResult =
from product in eshaktiDb.Products
join oivs in corpDb.OrderitemvalueSplits on product.ProductId equals oivs.Productid
join order in corpDb.Orders on oivs.Orderid equals order.OrderID
where product.ColorWaysId != null && order.CrDate >= fromDate && order.CrDate <= toDate
group oivs by product.ColorWaysId into g
select new ColorwayReportResponse
{
colorwayId = (int)g.Key,
revenue = (decimal)g.Sum(o => o.ActItemvalue + o.Custom)
};
return queryResult.ToList();
}
}
How to fix this ? Can somebody help me with the query that would fit in, also since the query involves two different databases, how can I get my desired result ?
I would separate this out into 2 separate queries starting with your corpDb:
var queryResult = (select * from corpDb.OrderitemvalueSplits join order in corpDb.Orders on oivs.Orderid equals order.OrderID).ToArray();
Then I would use perform the corresponding join afterwards in the other context.
var products = select * from product in eshaktiDb.Products join oivs in queryResult.OrderitemvalueSplits on product.ProductId equals oivs.Productid where product.ColorWaysId != null && order.CrDate >= fromDate && order.CrDate <= toDate
group oivs by product.ColorWaysId into g
select new ColorwayReportResponse
{
colorwayId = (int)g.Key,
revenue = (decimal)g.Sum(o => o.ActItemvalue + o.Custom)
};
There are other possible solutions to this issue here.
I'm not sure the above would work exactly in your code but generally you are not allowed to join within 2 separate contexts in Entity framework but you are allowed to pass arrays and other values between requests to accomplish the same task.

How to create a left join instead of inner join?

I have an SQL query which i am converting to Linq and i want to use Left Join instead of Inner Join.
I have tried DefaultIfEmpty() method but i haven't had any luck.
The Sql query:
SELECT t0.*, t1.* FROM entity AS t0
LEFT JOIN migration_logs AS t1 ON (CAST(t0.id AS CHAR) = t1.ObjectId and 'SASParty' = t1.ObjectType)
where t1.status is null || t1.Status <> '1' ORDER BY t0.id LIMIT 0, 10;
The Linq Query:
Entities
.Join(Migration_logs,
e => new { id = e.Id.ToString(), ObjectType = "SASParty" },
mlog => new { id = mlog.ObjectId, mlog.ObjectType },
(e, mlog) => new {e,mlog})
.Where(result => result.mlog.Status == null || result.mlog.Status != "1").DefaultIfEmpty().ToList()
I am using linqpad and when i execute the linq query it generates the following sql query:
SELECT t0.*
FROM entity AS t0
INNER JOIN migration_logs AS t1
ON ((CAST(t0.id AS CHAR) = t1.ObjectId) AND (#p0 = t1.ObjectType))
WHERE ((t1.Status IS NULL) OR (t1.Status <> #p1))
Some minor differences in the original query and generated sql query are there but i hope the problem statement is clear.
Any help would be appreciated.
I was able to find a solution with the linq to sql query and using into clause.
(from e in Entities
join mlog in Migration_logs
on new { id = e.Id.ToString(), ObjectType = "SASParty" }
equals new { id = mlog.ObjectId, mlog.ObjectType }
into results
from r in results.DefaultIfEmpty()
where r.Status == null || r.Status != "1"
select new
{
e
})
you want to perform the .DefaultIfEmpty() method on the quantity that you want to perform a left join onto. maybe this code snippet helps you
from e in Entities
join ml in Migration_lpgs on new { id=e.Id.ToString(), ObjectType="SASParty" } equals new { id=ml.Id.ToString(), mlog.ObjectType } into j
from e in j.DefaultIfEmpty()
where ml.Status == null || ml.Status != "1"
select e

How can we perform a select into another select using Linq c# left join, count , sum, where

How can I convert my sql code into Linq format :
How can we perform a select into another select using Linq c# :
My sql code :
SELECT DepartementProjects.Label, a.Number FROM
(SELECT DepartementProjects.Label ,count(1) as Number FROM DepartementProjects
inner join Absences on DepartementProjects.Id = Absences.DepartementProjectID
where Absences.Profil='SHT'
group by DepartementProjects.Label ) a right join DepartementProjects on DepartementProjects.Label = a.Label;
My attempt :
var AbsByDepartmentADM = from department in _dbContext.DepartementProjects
join abs in _dbContext.Absences on department.Id equals abs.DepartementProjectID
into groupedResult
from groupedResultRight in groupedResult.DefaultIfEmpty()
group groupedResultRight by department.Label into grouped
let NumberOfAbsence = grouped.Count(t => t.DepartementProjectID != null)
let WorkedHours = grouped.Sum(a => a.WorkedHours != null ? a.WorkedHours : 0)
select new
{
DepartmentId = grouped.Key,
NumberOfAbsence,
WorkedHours,
AbsencesHours = (8 * NumberOfAbsence - WorkedHours),
};
If you are trying to translate SQL, translate any subselects first, then the main select, and translate in LINQ phrase order. Also, your LINQ adds some values not in the SQL, so I didn't try to change the SQL to match:
var sub = from dept in _dbContext.DepartementProjects
join abs in _dbContext.Absences on dept.Id equals abs.DepartementProjectID into absj
from abs in absj
where abs.Profil == "SHT"
group abs by dept.Label into absg
select new { Label = absg.Key, Number = absg.Count() };
var ans = from dept in _dbContext.DepartementProjects
join a in sub on dept.Label equals a.Label into lnj
from ln in lnj.DefaultIfEmpty()
select new { dept.Label, ln.Number };

How to Create the Left Join by using the group by data

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

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.

Categories

Resources