C# Linq Left Outer Join - c#

When allUserDepart is null other join fire a exception on line of join allDepartment. Because uD its null. How to fix this code?
join d in allDepartment on uD.DepartmentId equals d.DepartmentId into departmentJoin
--Ful Code is
var data = (from us in allUsers
join uR in allUserRoles on us.UserId equals uR.UserId into userRoleJoin
from uR in userRoleJoin.DefaultIfEmpty()
join r in allRoles on uR.RoleId equals r.RoleId
join uD in allUserDepartment on us.UserId equals uD.NewUserId into userDepJoin
from uD in userDepJoin.DefaultIfEmpty()
join d in allDepartment on uD.DepartmentId equals d.DepartmentId into departmentJoin
from d in departmentJoin.DefaultIfEmpty()

Related

Joining column with multiple tables LINQ

There is a table I want to join with different columns in different tables.
This is how so far I did this
var purchData = (from a in db.AppRequest
join e in db.Employee on a.Req_By equals e.Id
join c in db.Company on e.CompanyId equals c.Id
join d in db.Designation on e.DesignId equals d.Id
join l in db.Master_Locations on a.Req_Location equals l.Id
join dep in db.Department on e.DepId equals dep.Id
join p in db.Purchase on a.Id equals p.Req_Id
join pi in db.PurchasingItems on p.Id equals pi.Purchase_Id
join pd in db.PurchasingDetails on p.Id equals pd.Purchase_Id
join pds in db.PurchasingDetailsSup on pd.Id equals pds.PurchasingDetails_Id
join s in db.M_Supplier on pds.Supp_Id equals s.Id
join payMethod in db.Master_PayMethods on s.Pay_Method equals payMethod.Id
join poNo in db.ApprovedPoNumbers on p.Id equals poNo.Purchase_Id
where a.Id == id && pds.IsApproved == true
In db.ApprovedPoNumbers table has purchase_Id and Supplier_Id
In db.PurchasingDetailsSup table has purchase_Id and Supplier_Id
So I want to know that here join poNo in db.ApprovedPoNumbers on p.Id equals poNo.Purchase_Id line I want to join the db.ApprovedPoNumbers table purchase_Id,Supplier_Id with db.PurchasingDetailsSup table purchase_Id and Supplier_Id
You can achieve that by building two objects with the criterias you intend to match and use the equals operator on them:
on new {poNo.purchase_Id, poNo.Supplied_Id} equals new {pds.purchase_Id, pds.Supplier_Id} into details

Need help on Linq-to-SQL query (maybe nested query?)

I am asking for your help regarding a linq query to SQL.
Here is a part of the diagram of my database: https://imgur.com/xFBUm3q
My problem is in the following relationship: tbl_607_bottle and tbl_607_gaz_reporting, I can have several reportings for a bottle but reporting can only have one bottle.
I do this request but it's not satisfying.
var GazReportingWizardViewModel =
(from gr in db.tbl_607_gaz_reporting
join a in db.tbl_607_actors on gr.FK_ID_actors equals a.id
join bo in db.tbl_607_bottle on gr.FK_ID_bottle equals bo.ID
join loc in db.tbl_607_location on bo.FK_ID_location equals loc.ID
join cc in db.tbl_607_conformity_certificate on bo.FK_ID_conformity_certificate equals cc.ID
join j in db.tbl_607_join_bottle_gaz on bo.ID equals j.FK_ID_bottle
join g in db.tbl_607_gaz on j.FK_ID_gaz equals g.ID
join od in db.tbl_607_order_details on g.FK_ID_order_details equals od.ID
where loc.ID == Process
select new GazReportingWizardViewModel
{
bottle_conti_number = bo.bottle_conti_number,
pressure_value = gr.pressure_value,
reporting_date = gr.reporting_date,
first_name = gr.tbl_607_actors.first_name,
last_name = gr.tbl_607_actors.last_name,
expiration_date = cc.expiration_date,
content = od.content_comments
}).Distinct()
.OrderBy(t => t.reporting_date)
.ToList();
I want the last report on each bottle but it return all reports on each bottle.
Would you have an idea of ​​the solution?
Thank you for your time
Thank you so much!
I persisted in trying to solve the problem in a single query when the solution was so simple.
var GazReportingWizardViewModel = (from gr in db.tbl_607_gaz_reporting
join a in db.tbl_607_actors on gr.FK_ID_actors equals a.id
join bo in db.tbl_607_bottle on gr.FK_ID_bottle equals bo.ID
join loc in db.tbl_607_location on bo.FK_ID_location equals loc.ID
join cc in db.tbl_607_conformity_certificate on bo.FK_ID_conformity_certificate equals cc.ID
join j in db.tbl_607_join_bottle_gaz on bo.ID equals j.FK_ID_bottle
join g in db.tbl_607_gaz on j.FK_ID_gaz equals g.ID
join od in db.tbl_607_order_details on g.FK_ID_order_details equals od.ID
where loc.ID == Process
select new GazReportingWizardViewModel
{
bottle_conti_number = bo.bottle_conti_number,
pressure_value = gr.pressure_value,
reporting_date = gr.reporting_date,
first_name = gr.tbl_607_actors.first_name,
last_name = gr.tbl_607_actors.last_name,
expiration_date = cc.expiration_date,
content = od.content_comments
}).ToList();
var res = from element in GazReportingWizardViewModel
group element by element.bottle_conti_number
into groups
select groups.OrderByDescending(p => p.reporting_date).First();

select key after group

I am trying to select all they keys after i perform a group-by. It works if I put the group into a variable then perform the select on the variable, but not directly after the group. I don't know why.
This does not work:
var pureUsers = from u in userContext.Users
join ur in userContext.UserRoles on u.UserID equals ur.UserID
join r in userContext.Roles on ur.RoleID equals r.RoleID
join sm in userContext.SystemMasters on r.SystemMasterID equals sm.SystemMasterID
where sm.SystemName == "PURE"
group ur.UserRoleID by u.SAPID into g
select g.Key;
It's giving me the error, "'string' does not contain a definition for 'Key' and no extension method 'Key' accepting a first argument of type 'string' could be found"
However, it works like this:
var pureUsers = from u in userContext.Users
join ur in userContext.UserRoles on u.UserID equals ur.UserID
join r in userContext.Roles on ur.RoleID equals r.RoleID
join sm in userContext.SystemMasters on r.SystemMasterID equals sm.SystemMasterID
where sm.SystemName == "PURE"
group ur.UserRoleID by u.SAPID
var happy = pureUsers.Select(x => x.Key);
I also tried:
var pureUsers = (from u in userContext.Users
join ur in userContext.UserRoles on u.UserID equals ur.UserID
join r in userContext.Roles on ur.RoleID equals r.RoleID
join sm in userContext.SystemMasters on r.SystemMasterID equals sm.SystemMasterID
where sm.SystemName == "PURE"
group ur.UserRoleID by u.SAPID).Select(x => x.Key);
It gives me the same error. I don't see how this is any different than putting it into pureUsers then doing the select. Also, if there is a better way of doing this that doesn't involve a group-by, please tell me. I group it by SAPID because Users can have many UserRoles and I want a list of Users.SAPID where each SAPID is displayed once.
How about:
var pureUsers = (from u in userContext.Users
join ur in userContext.UserRoles on u.UserID equals ur.UserID
join r in userContext.Roles on ur.RoleID equals r.RoleID
join sm in userContext.SystemMasters on r.SystemMasterID equals sm.SystemMasterID
where sm.SystemName == "PURE"
select u.SAPID).Distinct();

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

Categories