LINQ query not returning expected results - c#

I am trying to join three SQL tables in LINQ c# for the below SQL
SELECT
rpp.*
FROM dbo.Orgs ao
LEFT JOIN dbo.Afflia rpa
ON rpa.AccountId = ao.ID
INNER JOIN dbo.reports rpp
ON rpp.Id = rpa.reporttId
WHERE ao.Name like '%xyz%'
above query returns data but the equivalent LINQ query doesn't as in below
from a in context.Orgs
join aff in context.Afflia on a.ID equals aff.AccountId
join prescriber in context.Reports on aff.reportId equals prescriber.Id
where a.ORG_NAME.Contains("xyz")
May I know where the mistake is?

In LINQ you did INNER join but In SQL, you did LEFT join.
Try this instead:
from a in context.Orgs
join aff in context.Afflia on a.ID equals aff.AccountId into affs
from aff in affs.DefaultIfEmpty()
join prescriber in context.Reports on aff.reportId equals prescriber.Id
where a.ORG_NAME.Contains("xyz")

In your SQL you are doing a LEFT join to dbo.Afflia, but in your LINQ you are doing an inner join. You need to add "DefaultIfEmpty(), eg
from aff in context.Afflia.Where(join condition here).DefaultIfEmpty()

You could do:
var prescribers = (from a in context.Orgs
from aff in context.Afflia.Where(aff => aff.AccountId == a.ID)
from prescriber in context.Reports.Where(pres => pres.Id == aff.reportId)
where a.ORG_NAME.Contains("xyz")
select prescriber)
.ToList();

Related

How to handle linq join query when join on id is not available in the table c#

I am not trying to join my table using left outer join in LINQ where one of my join conditions does not satisfy. How can I still get the default record in my dataset? My SQL query runs perfectly fine but my join query is not returning the data.
Below is my SQL query where my left outer join works fine:
select
w.issueid as Issue
from worklog w
join jiraissue as j on w.issueid=j.ID
join issuetype AS ty ON ty.ID = j.issuetype
join project AS p on p.ID=j.PROJECT
left outer join customfieldvalue cfv on cfv.ISSUE = w.issueid
Below is my LINQ query in C# where if cfv.issue in the last join is not available in the table, I want to still return the default column.
var data = (from w in worklogs
join i in issuetypes on j.issuetype equals i.ID
join p in projects on j.PROJECT equals p.ID into table0
from c in table0.DefaultIfEmpty()
join cfv in customfieldvalues on w.issueid equals cfv.ISSUE into table1
from d in table1.DefaultIfEmpty()
{
IssueKey = l.Key.pkey + '-' + l.Key.issuenum,
Hours = l.Sum(w => w.timeworked)
}).ToList();
Any help is appreciated.
Thank you.

ef core left join with "in" conditions

i have many ids of persons that i want see group is Assigned to this personŲŒ
i have sql query like this
SELECT *
FROM cor.[Group] AS g
LEFT JOIN cor.PersonGroup AS pg ON
g.Id=pg.GroupId AND
pg.PersonId IN (1,2)
and i want to give linq query for this
i write this linq query
from g in _context.Groups join
pg in _context.PersonGroups.Where(pp =>personIds.Contains( pp.PersonId))
on g.Id equals pg.GroupId
But this is different from what I want
Try the following:
var persons = from grp in _context.Groups
join pg in _context.PersonGroups on grp.Id equals pg.GroupId
where personIds.Contains(pg.PersonId)
select pg;

LINQ Left Join with multiple ON OR conditions

I'm sorry for telling that I've a little bit weak on LINQ, I always do write SQL query before I start working on the complicated LINQ.
I want to ask that how to convert this SQL Query into LINQ with LEFT JOIN with multiple ON conditons with the OR operator.,
m.MerchandiseId will be use for twice in ON condition
SELECT
*
FROM
Inbox AS i
INNER JOIN [User] AS u ON i.FromUserId = u.UserId
LEFT OUTER JOIN Merchandise AS m ON
u.MerchandiseId = m.MerchandiseId
OR
i.ToMerchantId = m.MerchandiseId
WHERE
i.ToCompanyId = 10
OR
i.FromCompanyId = 10
var message = (from i in db.Inbox
join u in db.User on i.FromUserId equals u.UserId
join m in db.Merchandise on u.MerchandiseId equals m.MerchandiseId //here I want to ON i.MerchantId = m.MerchandiseId, but it doesn't allow
where i.ToCompanyId == user.CompanyId || i.FromCompanyId == user.CompanyId
orderby i.CreatedAt descending
group m.MerchandiseId by new { m.MerchandiseId, m.MerchandiseName } into grp
select new
{
MerchandiseId = grp.Key.MerchandiseId,
MerchandiseName = grp.Key.MerchandiseName,
InboxMessage = (from e in db.Inbox
join us in db.User on e.FromUserId equals us.UserId
join mer in db.Merchandise on us.MerchandiseId equals mer.MerchandiseId
where mer.MerchandiseId == grp.Key.MerchandiseId
orderby e.CreatedAt descending
select e.InboxMessage).FirstOrDefault(),
CreatedAt = (from e in db.Inbox
join us in db.User on e.FromUserId equals us.UserId
join mer in db.Merchandise on us.MerchandiseId equals mer.MerchandiseId
where mer.MerchandiseId == grp.Key.MerchandiseId
orderby e.CreatedAt descending
select e.CreatedAt).FirstOrDefault(),
}).ToList();
The bottom LINQ Query I've write for it. However, I just can work on the left join with multiple ON clause in LINQ. Appreciate if someone would help me on this. Thanks!
I don't believe Linq supports the use of the OR operator with multiple columns, but that said, I wouldn't use OR even in SQL as it makes the join's intention unclear and it also obscures where the data originated from - it also isn't immediately clear what happens if there are multiple matches for each column. Instead I would JOIN twice on the different columns and let the projection-clause handle it:
SELECT
*
FROM
Inbox
INNER JOIN [User] AS u ON i.FromUserId = u.UserId
LEFT OUTER JOIN Merchandise AS userMerchant ON u.MerchandiseId = userMerchant.MerchandiseId
LEFT OUTER JOIN Merchandise AS inboxMerchant ON Inbox.ToMerchantId = inboxMerchant .MerchandizeId
WHERE
Inbox.ToCompanyId = 10
OR
Inbox.FromCompanyId = 10
This can then be translated into Linq using the LEFT OUTER JOIN approach ( How to implement left join in JOIN Extension method )
Note that if you're using Entity Framework then you don't need to worry about doing any of this at all! Just use Include:
var query = db.Inbox
.Include( i => i.User )
.Include( i => i.User.Merchandise )
.Include i => i.Merchandise )
.Where( i => i.ToCompanyId = 10 || i.FromCompanyId == 10 );

Join in LINQ and Entity Framework

In SQL I to get the distinct statement, I used join to get it as below
select distinct
col1
from
table1 a
inner join
table2 b on a.code = b.vcode
How can the same be implemented in LINQ over Entity Framework?
Please suggest me.
You can also use method syntax:
var query = table1.Join(table2,
a => a.code,
b => b.vcode,
(a,b) => a.col1)
.Distinct();
var result = (from a in table1
join b in table2 on a.code equals b.vcode
select a.col1).Distinct();

How to use AND operator in LINQ Join

I have following SQL Query
SELECT * FROM KDMS_dynamic vd
INNER JOIN KDMS_definition tblKDMS ON tblKDMS.SystemID=vd.SystemID
LEFT OUTER JOIN KDMS_typeid tblKDMSType ON tblKDMS.TypeId=tblKDMSType.TypeId
INNER JOIN KDMS_configuration tblKDMSConfig ON tblKDMS.SystemID=tblKDMSConfig.SystemID
AND tblKDMSConfig.ConfigurationDate = (SELECT MAX(ConfigurationDate)
FROM KDMS_configuration vc
WHERE vc.SystemID=tblKDMSConfig.SystemID)
AND vd.LastUpdated=(SELECT MAX(LastUpdated) FROM KDMS_dynamic vd
WHERE vd.SystemID=tblKDMS.SystemID)
WHERE
DeletionDate IS NULL
AND LongDescription IS NOT NULL
AND tblKDMS.TypeId <> 1
As I have try convert the same in to LINQ but I can not due to AND OPERATOR use in Inner Join.
I am not aware how to use And Operator in LINQ , JOIN
As folloing the linq code which i try.
IQueryable<getKDMS> query = (from VD in this._db.GetTable<KDMS_dynamic>()
join TblKDMS in this._db.GetTable<KDMS_definition>() on VD.SystemID equals TblKDMS.SystemID
join TblKDMSType in this._db.GetTable<KDMS_typeid>().DefaultIfEmpty() on TblKDMS.TypeID equals TblKDMSType.TypeID
join TblKDMSConfig in this._db.GetTable<KDMS_configuration>() on TblKDMS.SystemID equals TblKDMSConfig.SystemID
&& TblKDMSConfig.ConfigurationDate == (from TblKDMS_conf in this._db.GetTable<KDMS_configuration>()
where TblKDMS_conf.SystemID == TblKDMSConfig.SystemID
select TblKDMS_conf.ConfigurationDate).Max())
As i have try with && but it did not work....
it is done as on new{x.field1,x.field2} equals new{y.field1,y.field2}
var somedata = (from TblKDMS_conf in this._db.GetTable<KDMS_configuration>()
where TblKDMS_conf.SystemID == TblKDMSConfig.SystemID select TblKDMS_conf.ConfigurationDate).Max();
Queryable<getKDMS> query = (from VD in this._db.GetTable<KDMS_dynamic>()
join TblKDMS in this._db.GetTable<KDMS_definition>() on VD.SystemID equals TblKDMS.SystemID
join TblKDMSType in this._db.GetTable<KDMS_typeid>().DefaultIfEmpty() on TblKDMS.TypeID equals TblKDMSType.TypeID
join TblKDMSConfig in this._db.GetTable<KDMS_configuration>() on new {TblKDMS.SystemID,TblKDMSConfig.ConfigurationDate} equals new{TblKDMSConfig.SystemID,somedata}
Move the AND condition to your WHERE clause. Writing
SELECT * FROM Table1
INNER JOIN Table2 ON *first condition* AND *second condition*
WHERE *third condition*
is exactly the same as writing
SELECT * FROM Table1
INNER JOIN Table2 ON *first condition*
WHERE *second condition* AND *third condition*
I think you need to use the where operator in place of the &&.

Categories