multiple join on conditions sql to linq - c#

how can i change the sql below to a linq.
select distinct * from dbo.TbleA a
left outer join dbo.TbleB b on a.schid = b.schid
left outer join dbo.TbleC c on b.addrid=c.addrid
and c.userid=a.userid
where b.addrid=1
here is my linq version which is causing error:
from a in db.TbleA
join b in db.TbleB on a.schid equals b.schid
join c in db.TbleC on new { w = b.addrid, z = a.userid } equals new { w=(int?)c.addrid, z=c.userid}
where (b.addrid == 1)
i am getting error around here:
join c in db.TbleC on new { w = b.addrid, z = a.userid } equals new {
w=(int?)c.addrid, z=c.userid}
i do understand where the problem is i am comparing to two tables in my join.
thanks and the error is:
"the type of one of the expressions in the join clause is incorrect""Type inference failed in the call to join"
b.addrid - int,
a.userid - string,
c.addrid - int?
c.userid - string

We can't really tell what's wrong with your current query in terms of compilation without knowing the types involved, but it wouldn't be equivalent to your original SQL anyway, as you want left outer joins. I suspect you want something more like:
from a in db.TbleA
join b in db.TbleB on a.schid equals b.schid into bs
from b in bs.DefaultIfEmpty()
join c in db.TbleC on new { w = (int?)b?.addrid, z = a.userid }
equals new { w = c.addrid, z = c.userid } into cs
from c in cs.DefaultIfEmpty()
where (b.addrid == 1)
That's if you can use C# 6 with the null conditional operator, of course. If not, you would at least logically need:
from a in db.TbleA
join b in db.TbleB on a.schid equals b.schid into bs
from b in bs.DefaultIfEmpty()
join c in db.TbleC on new { w = (b == null ? default(int?) : (int?)b.addrid), z = a.userid }
equals new { w = c.addrid, z = c.userid } into cs
from c in cs.DefaultIfEmpty()
where b == null || b.addrid == 1

I suspect your error is caused by trying to compare anonymous classes within a LinQ statement which are not of the same type. I suggest you change the join to the following:
from a in db.TbleA
join b in db.TbleB on a.schid equals b.schid
join c in db.TbleC on new { w = (int?)b.addrid, z = a.userid } equals new { w=(int?)c.addrid, z=c.userid}
where (b.addrid == 1)

Related

How to make left join and group by in linq?

I want to join 3 tables 2 of them inner join one of them left join after that i want to make group by. However, it gives an error. How can I handle that ?
this is code :
var people = from u in db.User.ToList()
join o in db.Offer.ToList() on u.UserId equals o.UserID where o.Statu == "Accepted"
join oz in db.log.ToList() on new { x1 = u.UserId.ToString(), x2 = o.CampaignId.ToString() } equals new { x1 = oz.ID, x2 = oz.CampaignID } into ps
from tbl in ps.DefaultIfEmpty()
group new { u, o, tbl } by new { u.UserId, o.CampaignId, o.Target, tbl.ID} into grp
select new { Username = grp.Key.UserId, CampaignID= grp.Key.CampaignId, Target = grp.Key.Target, id = grp.Key.ID};
Error occurs when i use tbl in group by. But i need to use it. I think some values comes null so it gives an error. How can i handle this ?

Linq, join and null how to check a value

I try to join two collection into one. If my second is empty I just need a null value, here is my code (it's correct if com is not empty)
var tmp = List{ Elem {long UserID; string tmpContent} };
var com = List{ Comment{long UserID; string Content} } ;
var res = from t in tmp
group t by t.UserID into g
join c in com on g.Key equals c.UserID
select new AnswerSet(new List<Answer>(g), c.Content);
I would like to get AnswerSet(g, Content) ou AnswerSet(g, null) the problem, I guess, is with g.Key equals c.UserID when com is empty
Basically what you want is a left outer join. you can do that by using join into instead of just join.
var res = from t in tmp
group t by t.UserID into g
join c in com on g.Key equals c.UserID into j
from subc in j.DefaultIfEmpty()
select new AnswerSet(new List<Answer>(g), subc != null ?subc.Content : null);

Why the following query results in an exception?

The following query results in the exception:
"Unable to cast object of type 'System.Linq.Expressions.TypedConstantExpression' to type 'SD.LLBLGen.Pro.LinqSupportClasses.ExpressionClasses.SetExpression'.".
What could be the problem?
return (from ubt in meta.TableUbt
join tc in meta.TableTc on ubt.TCId equals tc.Id
where ubt.Ar110aid == ar110AId && tc.IsPayment
group ubt by new { ubt.Ar110aid, ubt.TCId } into tempTrans
join pyd in meta.TablePyd on tempTrans.Key.Ar110aid equals pyd.Ar110Aid
join pm in meta.TablePm on pyd.Ar110Id equals pm.Id
join tly in TableTly on new { pyd.TyId, ChrgTransId = tempTrans.Key.TCId }
equals new { tly.TyId, tly.ChrgTransId }
join cr in meta.TableCr on
new
{
TyId = (int?)pyd.TyId,
TxLevId = (int?)tly.TxLevId,
Ar101Id = (int?)pm.Ar101Id
}
equals
new
{
cr.TyId,
cr.TxLevId,
cr.Ar101Id
}
join crd in meta.TableCrd on cr.Id equals crd.TableCrId
where crd.StartingLimit <= tempTrans.Sum(b => b.Amount) &&
tempTrans.Sum(b => b.Amount) <= crd.EndingLimit
select crd.Id).FirstOrDefault();
Probably problem is in joining on TableTly. It seems to be local data set. and it's prohibited to join Db data and in-memory objects.

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.

Convert special SQL query to Linq

do you know how write this SQL Query to linq ?
SELECT *
FROM
a
INNER JOIN b
ON a.FkSubmissionId = b.Id
RIGHT JOIN c
ON a.FkItemId = c.Id
WHERE
(b.FkUserId = '...' OR b.FkUserId is null)
and
(c.FkTenderId = 2)
I use Linquer and the best I have from the tool is that :
Linq :
from
items in _context.Items
from
si in _context.si
join s in _context.s
on new { fki = si.fki } equals new { fki = s.Id }
into
submissions_join
from
s in submissions_join.DefaultIfEmpty()
...
Result in SQL :
SELECT *
FROM
[Items] AS [t0]
CROSS JOIN [SubmissionsItems] AS [t1]
LEFT OUTER JOIN [Submissions] AS [t2]
ON [t1].[FkSubmissionId] = [t2].[Id]
WHERE
(([t2].[FkUserId] = #p0) OR (([t2].[FkUserId]) IS NULL))
AND
([t0].[FkTenderId] = #p1)
So the final result it not what I get from the query I need...
Thank you for your help !!!
Try this:
var part1 =
from x in a
join y in b on x.FkSubmissionId equals y.Id
where b.FkUserId = "..."
select new {x, y};
var part2 =
from c in z
where c.FkTenderId == 2
join xy in part1
on z.Id equals xy.x.FkItemId
into xys
from xy in xys.DefaultIfEmpty()
select new {xy.x, xy.y, z};
I would reorder your query so you can use a left join instead of a right join
var query = from c in context.C
from a in context.A.Where(x => c.Id == x.FkItemId)
.DefaultIfEmpty()
join b in context.B on a.FkSubmissionId equals b.id
where b.FkUserId == '...' || b.FkUserId == null
where c.FkTenderId == 2
select new {
a,
b,
c
};

Categories