Linq Joins only working when all tables have data - c#

Below you can find my problem. My view only loops through the data when both of "DocentenCompetenties" and "DocentenLocaties" is filled in. This is a problen because I want to be able to loop them even if one of them doens't have any data
var ShowCompetenties = from d in db.Docent
join dc in db.DocentenCompetenties on d.DocentID equals dc.DocentID
join c in db.Competenties on dc.CompetentiesID equals c.CompetentiesID
join dl in db.DocentenLocaties on d.DocentID equals dl.DocentID
where d.DocentID == id
join l in db.Locaties on dl.LocatieID equals l.LocatieID
select new ShowCompetenties { Docenten = d, Competenties = c, DocentenCompetenties = dc, DocentenLocaties = dl, Locaties = l };
UPDATE
Current Error:
An exception of type 'System.NullReferenceException' occurred in App_Web_xp01otas.dll but was not handled in user code
Additional information: Object reference not set to an instance of an object.
var id = Convert.ToInt32(Session["id"]);
var LeftShowCompetenties = from d in db.Docent
join g1 in db.DocentenCompetenties on d.DocentID equals g1.DocentID into group1
from dc in group1.DefaultIfEmpty()
join c in db.Competenties on dc.CompetentiesID equals c.CompetentiesID
where d.DocentID == id
select new ShowCompetenties { Docenten = d, Competenties = c, DocentenCompetenties = dc};
var RightShowCompetenties = from d in db.Docent
join g3 in db.DocentenLocaties on d.DocentID equals g3.DocentID into group3 from dl in group3.DefaultIfEmpty()
where d.DocentID == id
join l in db.Locaties on dl.LocatieID equals l.LocatieID
select new ShowCompetenties { Docenten = d, Locaties = l, DocentenLocaties = dl };
var ShowCompetenties = LeftShowCompetenties.Union(RightShowCompetenties);
VIEW
<h4>Competenties</h4>
#foreach (var item in Model)
{
if(#item.DocentenCompetenties != null && #item.DocentenCompetenties.DocentID.ToString() != null) {
#item.Competenties.Name #Html.ActionLink("Delete", "DeleteCompetenties", new { id = item.DocentenCompetenties.DocentenCompetentiesID })
}
<h4>Docenten</h4>
#foreach (var item in Model)
{
if(#item.DocentenLocaties != null && #item.DocentenLocaties .DocentID.ToString() != null)
{
#item.Locaties.Name
}
}

You are doing an Inner join this way.
It sounds like you actually want to do an outer join.
Try this:
var ShowCompetenties = from d in db.Docent
join g1 in db.DocentenCompetenties on d.DocentID equals g1.DocentID into group1
from dc in group1.DefaultIfEmpty()
join g2 in db.Competenties on dc.CompetentiesID equals g2.CompetentiesID into group2
from c in group2.DefaultIfEmpty()
join g3 in db.DocentenLocaties on d.DocentID equals g3.DocentID into group3
from dl in group3.DefaultIfEmpty()
where d.DocentID == id
join l in db.Locaties on dl.LocatieID equals l.LocatieID
select new ShowCompetenties { Docenten = d, Competenties = c, DocentenCompetenties = dc, DocentenLocaties = dl, Locaties = l };
This is only a LEFT outer join however, if you wish to do a full outer join. You must first do a left, then a right outer join and finally merge (with Union()) the two.
EDIT
As per the comments, with regards to the error you're getting after the UNION:
var id = Convert.ToInt32(Session["id"]);
var LeftShowCompetenties = from d in db.Docent
join g1 in db.DocentenCompetenties on d.DocentID equals g1.DocentID into group1
from dc in group1.DefaultIfEmpty()
join c in db.Competenties on dc.CompetentiesID equals c.CompetentiesID
where d.DocentID == id
select new ShowCompetenties { Docenten = d, Competenties = c, Locaties = null, DocentenCompetenties = dc, DocentenLocaties = null};
var RightShowCompetenties = from d in db.Docent
join g3 in db.DocentenLocaties on d.DocentID equals g3.DocentID into group3
from dl in group3.DefaultIfEmpty()
where d.DocentID == id
join l in db.Locaties on dl.LocatieID equals l.LocatieID
select new ShowCompetenties { Docenten = d, Competenties = null, Locaties = l, DocentenCompetenties = null, DocentenLocaties = dl };
var ShowCompetenties = LeftShowCompetenties.Union(RightShowCompetenties);
(Check the added Locaties = null and Competenties = null in the constructors.)
VIEW
if (#item.DocentenCompetenties != null){}
if (#item.DocentenLocaties!= null){}

If you have navigation properties set up, it's much easier to left join:
var ShowCompetenties =
from d in db.Docent
where d.DocentID == id
from dc in d.DocentenCompetenties.DefaultIfEmpty()
let c = dc.Competenty
from dl in d.DocentenLocaties.DefaultIfEmpty()
let l = dl.Locaty
select new ShowCompetenties {
Docenten = d,
Competenties = c,
DocentenCompetenties = dc,
DocentenLocaties = dl,
Locaties = l };

Related

The specified LINQ expression contains references to queries that are associated with different contexts c#

I have this simple function that returns a query, but when I try to join 2 tables in different databases, the error raised: The specified LINQ expression contains references to queries that are associated with different contexts.
here is my code.
private object projectcycleFilter(int? pid, int? cid, int UserId)
{
string[] res = { null, "" };
int?[] resint = { null, 0 };
var access_user = (from p in geotagging.webpages_UsersInRoles join s in geotagging.UserProfiles on p.UserId equals s.UserId where p.UserId == UserId select p).ToList();
var x = new object();
var geotaggingquery = (from xx in geotagging.sub_project select xx).AsEnumerable();
var nfmsquery = (from p in nfmsdb.request_for_refund join lr in nfmsdb.lib_regions on p.region_code equals lr.region_code join lp in nfmsdb.lib_provinces on p.prov_code equals lp.prov_code join lc in nfmsdb.lib_cities on p.city_code equals lc.city_code join lb in nfmsdb.lib_brgy on p.brgy_code equals lb.brgy_code join gts in geotaggingquery on p.sub_project_id equals gts.sub_project_id select new { lb, lc, lp, lr, p, gts }).AsEnumerable();
if (access_user.Select(x => x.RoleId).FirstOrDefault() > 2)
{
nfmsquery = (from p in nfmsdb.request_for_refund join lr in nfmsdb.lib_regions on p.region_code equals lr.region_code join lp in nfmsdb.lib_provinces on p.prov_code equals lp.prov_code join lc in nfmsdb.lib_cities on p.city_code equals lc.city_code join lb in nfmsdb.lib_brgy on p.brgy_code equals lb.brgy_code join gt in nfmsdb.user_municipal_access on p.city_code equals gt.city_code join gts in geotaggingquery on p.sub_project_id equals gts.sub_project_id where gt.user_id == UserId && gt.selected == true select new { lb, lc, lp, lr, p, gts }).AsEnumerable();
}
if (!resint.Contains(pid))
{
nfmsquery = nfmsquery.Where(x => x.gts.project_type_id == pid);
}
if (!resint.Contains(cid))
{
nfmsquery = nfmsquery.Where(x => x.gts.cycle_id == cid);
}
var result = nfmsquery.Select(x => new
{
sub_project_id = x.p.sub_project_id,
sub_project_name = x.p.sub_project_name,
region_name = x.lr.region_name,
region_code = x.lr.region_code,
prov_name = x.lp.prov_name,
prov_code = x.lp.prov_code,
city_name = x.lc.city_name,
city_code = x.lc.city_code,
brgy_code = x.lb.brgy_code,
brgy_name = x.lb.brgy_name,
request_for_refund_id = x.p.request_for_refund_id,
total_sub_project_cost = x.p.total_sub_project_cost,
total_program_cost = x.p.total_program_cost,
region_director = x.p.region_director,
lbp_branch = x.p.lbp_branch,
address = x.p.address,
lcc_amount = x.p.lcc_amount,
account_name = x.p.account_name,
bank_no = x.p.bank_no,
amount_requested = x.p.amount_requested,
tranche_id = x.p.tranche_id,
prev_amount_release = x.p.prev_amount_release,
cumul_total_request = x.p.cumul_total_request,
date_created = x.p.date_created,
date_requested = x.p.date_requested,
brgy_chair_name = x.p.brgy_chair_name,
bspmc_name = x.p.bspmc_name,
ac_name = x.p.ac_name,
lprao_name = x.p.lprao_name,
lprao_date = x.p.lprao_date,
rpc_name = x.p.rpc_name,
rpm_name = x.p.rpm_name,
ac_date = x.p.ac_date,
rpc_date = x.p.rpc_date,
rpm_date = x.p.rpm_date,
updated_by = x.p.updated_by,
date_updated = x.p.date_updated,
isdeleted = x.p.isdeleted,
}).ToList();
return result;
}
I also try var geotaggingquery = (from xx in geotagging.sub_project select xx).ToList() and `var nfmsquery = (from p in nfmsdb.request_for_refund join lr in nfmsdb.lib_regions on p.region_code equals lr.region_code join lp in nfmsdb.lib_provinces on p.prov_code equals lp.prov_code join lc in nfmsdb.lib_cities on p.city_code equals lc.city_code join lb in nfmsdb.lib_brgy on p.brgy_code equals lb.brgy_code join gts in geotaggingquery on p.sub_project_id equals gts.sub_project_id select new { lb, lc, lp, lr, p, gts }).ToList();, nothing happens.
Thanks in advance

SQL to Linq: left join

I need to write linq query. I tried to write example in sql and it works great but I didn't manage to convert it to proper linq
This is my working sql query:
SELECT
pr.descr as product,
prm.Descr
, px.Value AS ParamValue
, prm.Unit AS Unit
, gx.TcPos
FROM [Product] pr
JOIN [PrGroup] prg ON pr.GroupId = prg.Id
LEFT JOIN [PrParamGroup] pg ON ISNULL(pr.PrParamGroupId, prg.PrParamGroupId) = pg.Id
CROSS JOIN [PrParam] prm
LEFT JOIN [PrParam2ProductX] px ON pr.Id = px.ProductId AND prm.Id = px.PrParamId
LEFT JOIN [PrParam2GroupX] gx ON prm.Id = gx.PrParamId AND pg.Id = gx.PrParamGroupId
WHERE
pr.Id = 123 AND
(px.PrParamId IS NOT NULL OR gx.PrParamId IS NOT NULL)
AND (gx.PrParamId <> -1 OR gx.PrParamId IS NULL)
AND (gx.PrParamId IS NOT NULL)
This is my linq attempt:
var productsDesc = (from pr in context.Product.Where(m => m.Id == 123)
join prg in context.PrGroup
on pr.GroupId equals prg.Id
join pg in context.PrParamGroup
on pr.PrParamGroupId equals pg.Id
from prm in context.PrParam
join px in context.PrParam2ProductX
on new { a = pr.Id, b = px.ProductId } equals new { a = prm.Id, b = px.PrParamId }
join gx in context.PrParam2GroupX
on new { prm.Id = gx.PrParamId } equals new { pg.Id = gx.PrParamGroupId }
select new
{
Name = prm.Descr,
Value = px.Value,
Unit = prm.Unit ?? ""
}).ToList();
Your linq dont implement left join and cross join
try this
var productsDesc = (from pr in context.Product.Where(m => m.Id == 123)
join prg in context.PrGroup
on pr.GroupId equals prg.Id
join pg in context.PrParamGroup
on pr.PrParamGroupId equals pg.Id into tmp1
from t1 in tmp1.DefaultIfEmpty()
from prm in context.PrParam
join px in context.PrParam2ProductX
on new { a = pr.Id, b = px.ProductId } equals new { a = prm.Id, b = px.PrParamId } into tmp2
from t2 in tmp2.DefaultIfEmpty()
join gx in context.PrParam2GroupX
on new { prm.Id = gx.PrParamId } equals new { pg.Id = gx.PrParamGroupId } into tmp3
from t3 in tmp3.DefaultIfEmpty()
select new
{
Name = prm.Descr,
Value = t2.Value,
Unit = prm.Unit ?? ""
}).ToList();

Linq To Sql Skip Take

I want to save each icon path into a variable, from the query bellow , only PathIcon1 has value . The remain path icon are empty
Query
using (CarteringServiceClientDataContext dc = new CarteringServiceClientDataContext())
{
result = (from a in dc.GetTable<tblSupplier>()
join b in dc.GetTable<tblCity>()
on a.CityId equals b.Id
join c in dc.GetTable<tblZone>()
on b.ZoneId equals c.Id
let r = (from re in dc.GetTable<tblClientReview>()
where re.SupplierId == a.Id
select re.note).Average()
let i = (from im in dc.GetTable<tblSupplierItem>()
where im.SupplierId == a.Id
select im.tblItem.IconPath).ToArray()
select new SearchResult
{
CompanyId = a.Id,
CompanyName = a.Company,
Localisation = a.Locality,
City = b.Name,
Zone = c.Name,
Rating = r.ToString(),
PathIcon1 = i.Take(1).SingleOrDefault(),
PathIcon2 = i.Skip(1).Take(1).SingleOrDefault(),
PathIcon3 = i.Skip(2).Take(1).SingleOrDefault(),
PathIcon4 = i.Skip(3).Take(1).SingleOrDefault(),
PathIcon5 = i.Skip(4).Take(1).SingleOrDefault()
}).ToList<SearchResult>();
}
A part from PathIcon1, the remaing PathIcon are null
using (CarteringServiceClientDataContext dc = new CarteringServiceClientDataContext())
{
result = (from a in dc.GetTable<tblSupplier>()
join b in dc.GetTable<tblCity>()
on a.CityId equals b.Id
join c in dc.GetTable<tblZone>()
on b.ZoneId equals c.Id
let r = (from re in dc.GetTable<tblClientReview>()
where re.SupplierId == a.Id
select re.note).Average()
let i = (from im in dc.GetTable<tblSupplierItem>()
where im.SupplierId == a.Id
select im.tblItem.IconPath).ToArray().Add("test")
select new SearchResult
{
CompanyId = a.Id,
CompanyName = a.Company,
Localisation = a.Locality,
City = b.Name,
Zone = c.Name,
Rating = r.ToString(),
PathIcon1 = i.Take(1).SingleOrDefault(),
PathIcon2 = i.Skip(1).Take(1).SingleOrDefault(),
PathIcon3 = i.Skip(2).Take(1).SingleOrDefault(),
PathIcon4 = i.Skip(3).Take(1).SingleOrDefault(),
PathIcon5 = i.Skip(4).Take(1).SingleOrDefault()
}).ToList<SearchResult>();
}
Try this if you are get PathIcon2 value as "test" your problem isn't skip or take. Just i list includes one item. Adn I think so.

Left outer join in linq on three table

var response = ( from e in db.tblEvents
join f in db.tblEventTypes on e.FightTypeId equals f.eventTypeId
into egroup
from e in egroup.DefaultIfEmpty()
join w in db.tblUserWebApp on e.ModifiedUserId equals w.Id
orderby e.LastUserModified descending
select new {
FightTypeName = f.eventTypeName,
EventID = e.EventID,
FightTypeId=e.FightTypeId,
Title = e.Title,
Date = e.Date,
Location = e.Location,
UserSelectFavoriteFlag =e.UserSelectFavoriteFlag ,
Price=e.Price,
UserPredictionFlag=e.UserPredictionFlag,
PredictionStartDate= e.PredictionStartDate ,
PredictionEndDate = e.PredictionEndDate,
ModifiedUserId = w.Id,
ModifiedUser = w.LoginName,
LastUserModified = e.LastUserModified,
});
return Ok(response);
how can i use left outer join since i have 3 table to join and i want to get all data from tblEvents table
Try this query
var response = ( from e in db.tblEventTypes
from f in db.tblEvents.where(x=>x.FightTypeId ==e.eventTypeId).DefaultIfEmpty()
from w in db.tblUserWebApp.where(x=>x.Id==f.ModifiedUserId)
orderby f.LastUserModified descending
select new {
FightTypeName = e.eventTypeName,
EventID = f.EventID,
FightTypeId=f.FightTypeId,
Title = f.Title,
Date = f.Date,
Location = f.Location,
UserSelectFavoriteFlag =f.UserSelectFavoriteFlag ,
Price=f.Price,
UserPredictionFlag=f.UserPredictionFlag,
PredictionStartDate= f.PredictionStartDate ,
PredictionEndDate = f.PredictionEndDate,
ModifiedUserId = w.Id,
ModifiedUser = w.LoginName,
LastUserModified = f.LastUserModified,
});

How to Join LINQ to another LINQ

i have a query like this
WITH CTE_KELOMPOKINFORMASI (KelompokInformasi, XBRLItem_ItemId)
AS (
SELECT a.Id AS KelompokInformasi, c.XBRLItem_ItemId
FROM XBRLNamespaces a INNER JOIN XBRLHypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN XBRLHypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
WHERE a.Id like '%KBIK_AAKL%')
SELECT f.KelompokInformasi, e.Name AS DimensionName, c.Id AS Domain,
d.Text AS Description FROM [dbo].[XBRLDefinitionRoleDomainItems] a
INNER JOIN [dbo].[XBRLDefinitionRoleDimensionItems] b
ON a.XBRLDefinitionRole_DefinitionRoleId = b.XBRLDefinitionRole_DefinitionRoleId
INNER JOIN XBRLItems c ON a.XBRLItem_ItemId = c.ItemId
INNER JOIN XBRLLabels d
ON a.XBRLItem_ItemId = d.XBRLItem_ItemId
INNER JOIN XBRLItems e
ON b.XBRLItem_ItemId=e.ItemId
INNER JOIN CTE_KELOMPOKINFORMASI f
ON b.XBRLItem_ItemId=f.XBRLItem_ItemId
WHERE b.XBRLItem_ItemId=f.XBRLItem_ItemId
i want to move this sql query to linq, i realized that CTE is impossible in LINQ. So i divide into 2 parts. First i create a var like this:
var KelompokInformasi = from x in ent.XBRLNamespaces
join y in ent.XBRLHypercubes on x.XBRLView_ViewId equals y.XBRLView_ViewId
join z in ent.XBRLHypercubeDimensionItems on y.XBRLHypercubeId equals z.XBRLHypercube_XBRLHypercubeId
where x.Id.Contains("KBIK")
select new
{
x.Id,
y.XBRLItem_ItemId
};
and in second part i create:
_list = (from a in ent.XBRLDefinitionRoleDomainItems
join b in ent.XBRLDefinitionRoleDimensionItems on a.XBRLDefinitionRole_DefinitionRoleId equals b.XBRLDefinitionRole_DefinitionRoleId
join c in ent.XBRLItems on a.XBRLItem_ItemId equals c.ItemId
join d in ent.XBRLLabels on a.XBRLItem_ItemId equals d.XBRLItem_ItemId
join e in ent.XBRLItems on b.XBRLItem_ItemId equals e.ItemId
join f in KelompokInformasi on b.XBRLItem_ItemId equals (int)f.XBRLItem_ItemId
where (b.XBRLItem_ItemId == (int)f.XBRLItem_ItemId)
select new MappingDomainRepository
{
KI = f.Id,
Dimension = e.Name,
Domain = c.Id,
Description = d.Text
}).ToList();
Where _list is from List<MappingDomainRepository> _list = new List<MappingDomainRepository>();
in my code above, i want to join my _list to var KelompokInformasi. In var kelompokInformasi I've got 47 rows but in _list I've got 0 data return.
What's wrong in my code? is it possible to join my _list to var kelompokInformasi?
You need to change the second part to:
var other = (from a in ent.XBRLDefinitionRoleDomainItems
join b in ent.XBRLDefinitionRoleDimensionItems on a.XBRLDefinitionRole_DefinitionRoleId equals b.XBRLDefinitionRole_DefinitionRoleId
join c in ent.XBRLItems on a.XBRLItem_ItemId equals c.ItemId
join d in ent.XBRLLabels on a.XBRLItem_ItemId equals d.XBRLItem_ItemId
join e in ent.XBRLItems on b.XBRLItem_ItemId equals e.ItemId
join f in KelompokInformasi on b.XBRLItem_ItemId equals (int)f.XBRLItem_ItemId
where (b.XBRLItem_ItemId == (int)f.XBRLItem_ItemId)
select new MappingDomainRepository
{
KI = f.Id,
Dimension = e.Name,
Domain = c.Id,
Description = d.Text,
XBRLItem_ItemId = a.XBRLItem_ItemId
};
...which adds in the XBRLItem_ItemId which use to join to the CTE.
Then join the two together. We have other (above) and KelompokInformasi from the CTE:
var result = from x in KelompokInformasi
join o in other on x.XBRLItem_ItemId equals o.XBRLItem_ItemId
select new {KelompokInformasi = o.KelompokInformasi,
DimensionName = o.Name,
Domain = o.Id,
Description = o.Text
};
..which appears to be the columns you exentually select.

Categories