How to use AND operator in LINQ Join - c#

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 &&.

Related

generated SQL Query changes based on different selection in Linq

I am converting an SQL query to LINQ. It has multiple inner, left and right joins. I'm checking the generated SQL from LINQ in every step. But the problem is based on the selection the generated sql query changes.
Below my Linq
var a = from freight in billingEntity.FreightCharges.AsNoTracking()
join service in billingEntity.ServiceTypes.AsNoTracking()
on freight.ServiceTypeId equals service.Id
join transport in billingEntity.TransportationTypes.AsNoTracking()
on freight.TransportationTypeId equals transport.Id
join division in billingEntity.DivisionDetails.AsNoTracking()
on freight.OriginId equals division.OriginID
join mail in billingEntity.Mailclasses.AsNoTracking()
on freight.MailClassId equals mail.MailClassId
into mailClassFreight
from mail in mailClassFreight.DefaultIfEmpty()
join process in billingEntity.ProcessingCategories.AsNoTracking()
on freight.ProcessingcategoryId equals process.ProcessingCategoryId
into processFreight
from processCategory in processFreight.DefaultIfEmpty()
select mail;
string v = a.ToString();
This generated SQL as
SELECT
[Extent3].[MailClassId] AS [MailClassId],
[Extent3].[MailClassName] AS [MailClassName],
[Extent3].[CreatedDate] AS [CreatedDate]
FROM [dbo].[FreightCharges] AS [Extent1]
INNER JOIN [dbo].[DivisionDetails] AS [Extent2] ON [Extent1].[OriginId] = [Extent2].[OriginID]
LEFT OUTER JOIN [dbo].[Mailclass] AS [Extent3] ON [Extent1].[MailClassId] = [Extent3].[MailClassId]
WHERE ([Extent1].[ServiceTypeId] IS NOT NULL) AND ([Extent1].[TransportationTypeId] IS NOT NULL)
Where I can see the dbo.ProcessingCategory is missing in the join.
If I do select processCategory the SQL generates with missing dbo.MailClass.
The SQL query I am trying to convert to LINQ is below
select * from
dbo.FreightCharges as fc
inner join dbo.ServiceType as st
on fc.ServiceTypeId = st.Id
inner join dbo.TransportationTypes as tt
on fc.TransportationTypeId = tt.Id
inner join dbo.DivisionDetails as dd
on fc.OriginId = dd.OriginId
left join dbo.Mailclass as mc
on fc.MailClassId = mc.MailClassId
left join dbo.ProcessingCategory as pc
on fc.ProcessingcategoryId = pc.ProcessingCategoryId
right join dbo.ContentTitle as ct
on fc.ContentTitleId = ct.ContentTitleId
inner join dbo.AccountDetails as ac
on ct.AccountId = ac.AccountId
where
fc.EffectiveThruDate >= '9999-12-31'
or
fc.EffectiveThruDate is null
You can change your query joins to left joins like this.
select * from
dbo.ContentTitle ct
inner join dbo.AccountDetails as ac
on ct.AccountId = ac.AccountId
left join dbo.FreightCharges as fc
on fc.ContentTitleId = ct.ContentTitleId and fc.EffectiveThruDate >= '9999-12-31'
left join dbo.ServiceType as st
on fc.ServiceTypeId = st.Id
left join dbo.TransportationTypes as tt
on fc.TransportationTypeId = tt.Id
left join dbo.DivisionDetails as dd
on fc.OriginId = dd.OriginId
left join dbo.Mailclass as mc
on fc.MailClassId = mc.MailClassId
left join dbo.ProcessingCategory as pc
on fc.ProcessingcategoryId = pc.ProcessingCategoryId
Linq equivalent
from ct in ContentTitles
join ac in AccountDetails on ct.AccountId equals ac.AccountId
join fc in FreightCharges on ct.ContentTitleId equals fc.ContentTitleId into lfc
from flfc in lfc.Where(f => f.EffectiveThruDate >= new DateTime(9999,12,31)).DefaultIfEmpty()
join st in ServiceTypes on flfc.ServiceTypeId equals st.Id into lst
from flst in lst.DefaultIfEmpty()
join tt in TransportationTypes on flfc.TransportationTypeId equals tt.Id into ltt
from fltt in ltt.DefaultIfEmpty()
join dd in DivisionDetails on flfc.OriginId equals dd.OriginId into ldd
from fldd in ldd.DefaultIfEmpty()
join mc in Mailclasses on flfc.MailClassId equals mc.MailClassId into lmc
from flmc in lst.DefaultIfEmpty()
join pc in ProcessingCategories on flfc.ProcessingcategoryId equals pc.ProcessingCategoryId into lpc
from flpc in lst.DefaultIfEmpty()
select new {ct, ac, lfc, lst ,ltt, ldd, lmc, lpc}

LINQ query not returning expected results

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();

Linq to sql Distinct after join

I have a join query and i want to filter the result of this query by using distinct. I want to get only one of the shoes which has same brand, model, primary color and secondary color. How can i make this ? Here is my join query.
var query = from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
where s.Quantity > 0
orderby m.ModelName
select new
{
s.ShoeID,
m.ModelName,
m.Price,
b.BrandName,
i.ImagePath
};
I found the solution. This query does approximately what i want to do
var query = from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
group new {b,m,s,i} by new {b.BrandName,m.ModelName,m.Price,s.ShoeID,s.PrimaryColor,s.SecondaryColor,i.ImagePath} into g
select new {g.Key.ShoeID,g.Key.BrandName,g.Key.ModelName,g.Key.ImagePath,g.Key.Price};
Remove price from the output and use Distinct() like this:
var query = (from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
where s.Quantity > 0
orderby m.ModelName
select new
{
s.ShoeID,
m.ModelName,
b.BrandName,
i.ImagePath
}).Distinct();

LINQ: Inner join 2 table + outer join 1 table

I have 2 inner joins (3 tables) but I don't know and I find it hard to implement my research about outer join in LINQ. How do I change the last inner join to outer join, such that column will still join even if the column (Role) is null?
Here's an existing SQL version of this which I want to convert to LINQ:
SELECT dbo.EmployeeAccess.id, dbo.EmployeeAccess.EmpNo, dbo.EmployeeAccess.RoleID, dbo.EmployeeAccess.Active, dbo.EmployeeAccessLevel.Role,
dbo.View_HCM.LNameByFName
FROM dbo.EmployeeAccess LEFT OUTER JOIN
dbo.EmployeeAccessLevel ON dbo.EmployeeAccess.RoleID = dbo.EmployeeAccessLevel.id INNER JOIN
dbo.View_HCM ON dbo.EmployeeAccess.EmpNo = dbo.View_HCM.EmpNo
LINQ I now have with 2 inner joins:
(from ea in context.EmployeeAccesses
join vh in context.View_HCM on (Int16)ea.EmpNo equals vh.EmpNo
join rl in context.EmployeeAccessLevels on ea.RoleID equals rl.id
select new EmployeeWithEmail{
EmpNum = ea.EmpNo ?? 0,
EmailAddress = vh.EmailAddress,
LNameByFname = vh.LNameByFName,
Active2 = ea.Active ?? false
}).ToList();
}
Linq's outer join syntax uses 2 parts. First an into then DefaultIfEmpty
In your case, an outer join might look like this:
(from ea in context.EmployeeAccesses
join vh in context.View_HCM on (Int16)ea.EmpNo equals vh.EmpNo
join rl in context.EmployeeAccessLevels on ea.RoleID equals rl.id into outer_join
from subjoin in outer_join.DefaultIfEmpty()
select new EmployeeWithEmail{
EmpNum = ea.EmpNo ?? 0,
EmailAddress = vh.EmailAddress,
LNameByFname = vh.LNameByFName,
Active2 = ea.Active ?? false
}).ToList();
There are many tutorials on how to create the outer join in LINQ.

c# linq not equals variation

I have a linq query w/ entity frameworks that works and gets the needed information, but now i am having trouble doing the opposite.
Currently it gets all the data that is needed using the joins to link tables but i need to to get some data that is not match some of the joins.
I know you can only use "equals" om linq, but i need info that is not equals
i.e. join ec in c.IsoNe on ap.idLook not equals ec.idAll
Below is the working code, but not how i need it now. any help would be appreciated...
var test = (from bil in bilats
join ap in c.Allegro on bil.idAll equals ap.idAll
join ec in c.IsoNe on ap.idLook equals ec.idAll
join cb in c.Comp on ap.idCompBuy equals cb.idComp
join cs in c.Com on ap.idCompSell equals cs.idComp
join iby in c.IsoNe on cb.idComp equals iby.idComp
join iss in c.IsoNe on cs.idComp equals isl.idComp
orderby bil.HBegin ascending
where bil.HBegin >= ec.DateTStart
where bil.HBegin < ec.DateTEnd
select new
{
Cont = ec.ContractID,
ContType = ap.idScheduleType,
Sel = isel.ISONE1,
Buy = ibel.ISONE,
HBegin = bil.HBegin,
}).ToList();
As far as I know, you'll have to create a Cartesian product and then use a where-condition to filter it. (I'm making the perhaps rash assumption that you want an inner join rather than a left join, but an inner join is what the join keyword represents.) Something like this:
var test = (from bil in bilats
join ap in c.Allegro on bil.idAll equals ap.idAll
from ec in c.IsoNe where ap.idLook != ec.idAll
join cb in c.Comp on ap.idCompBuy equals cb.idComp
join cs in c.Com on ap.idCompSell equals cs.idComp
join iby in c.IsoNe on cb.idComp equals iby.idComp
join iss in c.IsoNe on cs.idComp equals isl.idComp
orderby bil.HBegin ascending
where bil.HBegin >= ec.DateTStart
where bil.HBegin < ec.DateTEnd
select new
{
Cont = ec.ContractID,
ContType = ap.idScheduleType,
Sel = isel.ISONE1,
Buy = ibel.ISONE,
HBegin = bil.HBegin,
}).ToList();
Sounds like a join might be the wrong approach. Have a look at unions or subqueries
C# linq union question
how to do subquery in LINQ

Categories