How to achieve Left Excluding JOIN using LINQ? - c#

How to achieve Left Excluding JOIN using LINQ?
In SQL:
SELECT <select_list>
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

You need DefaultIfEmpty() for the LEFT JOIN, then you can check if the joined value is null:
var result = from a in Table_A
join b in Table_B on a.Key equals b.Key into j
from b in j.DefaultIfEmpty()
where b == null
select new { ... };

Easier would be to write like this:
var result = from a in Table_A
where !Table_B.Any(b => b.Key == a.key)
select new { ... };

An even faster way
var result = from a in Table_A
where !Table_B.Select(b => b.Key).Contains(a.Key)
select new { ... };

Related

Inner select query in linq query c#

I want to check values that are present in other table, not from fixed list or array. here is an example of what I need. Actually I am querying EF.
Database_EF db = new Database_EF();
var listA = (from a in db.a
where a.id in
(from b in db.b
join c in db.c on b.id equals c.id
where c.col1 equals 'something'
select b.id)
select a.id).ToList();
I am new to linq. Thanks.
Should be something like this:
var listA = (from a in db.a
where (from b in db.b
join c in db.c on b.id equals c.id
where c.col1 == "something"
select b.id).Contains(a.id)
select a.id).ToList();

Can we use if statement in linq for deciding to join or not?

I want to include a table in some conditions in Linq.
I am looking for sth like this:
var query = from x in context.Messages
if(x.senderID != 0)
{
join et in context.ETs on x.senderID equals et.ID
}
where x.Getter == SSN
select new { x.id, x.message}
Is this kind of approach possible or do I have to write two different linq queries and then I will combine them?
var query = from a in context.Messages
join b in context.ETs
on a.senderID equals b.ID
into temp
from b in temp.DefaultIfEmpty()
where a.Getter == SSN
select new { a.id, a.message}

entity framework - inner join to left join

Good day! I need transform join to left join in my query -
var query = (from sections in context.Sections
join themes in context.Themes on sections.SectionId equals themes.SectionId
join comments in context.Comments on themes.ThemeId equals comments.ThemeId
select new { sections.SectionId, sections.SectionTitle, themes.ThemeId, comments.CommentId } into x
group x by new { x.SectionId, x.SectionTitle } into g
select new SectionInfo
{
SectionId = g.Key.SectionId,
SectionTitle = g.Key.SectionTitle,
ThemeCount = g.Select(s => s.ThemeId).Count(),
CommentCount = g.Select(s => s.CommentId).Count()
}).ToList();
- please, i have no idea(
You need to use DefaultIfEmpty
One way is like this:
from themes in context.Themes.Where(x => sections.SectionId == x.SectionId)
.DefaultIfEmpty()
Alternate way
join themes in context.Themes on sections.SectionId equals themes.SectionId into themesGroup
from themes in themesGroup.DefaultIfEmpty()

linq join 3 tables with or condition

I need to create a statement in LINQ with 3 tables and OR condition.
My function receives an integer, lets call it intZ. I have 3 tables: tableA, tableB and tableC.
tableA has columns int1, int2 and intB. intB is related to tableB.
problem: int1 or int2 of tableA can be intZ and it has to match with one tableC record.
I need an OR condition, but I have no idea where to place it. Does it go in the where clause? Or in the equals clause?
At the moment, I know how to join 3 tables, but the condition is killing me.
What is the difference between the two ways to create statements in linq? Is there a performance impact?
edit: Okay, now I think it's more clear. intZ has to be related with intC from tableC, and this number can be int1 or int2 of tableA.
Just add it to a Where. In Linq2Sql this will be translated to an inner join (with or) on tableB
from a in tableA
from b in tableB.Where(x => x.A == a.A || x.B == a.B)
select new { a, b };
You can't use an "or" condition in joins in LINQ, as it only supports equijoins. But you should be able to do it in a where clause with no problems. For example:
var query = from rowC in tableC
where rowC.intC == intZ
from rowA in tableA
where rowA.int1 == rowC.intC || rowA.int2 == rowC.intC
join rowB in tableB on rowA.intB equals rowB.intB
select new { rowA, rowB, rowC };
This may be helpful.
var locations = from r1 in
(from a in context.A
join b in context.B
on a.ID equals b.ID
select new
{
a.Prop1,
a.Prop2,
b.Prop3,
b.ID
})
join c in context.C
on r1.ID equals c.ID
select new
{
r1.Prop1,
r2.Prop2,
r2.Prop3,
c.Prop4
};
For the life of me, I couldn't get the .Where to work in my query (perhaps it's how I'm using LinqPad) but I was able to get the following to work:
from s in Stores
join a in Areas on s.AreaID equals a.ROWID
join r in Regions on a.RegionID equals r.ROWID
join e in Employees on 1 equals 1 // <-- produces a cartesian product
join t in Titles on e.TitleID equals t.ROWID
where e.AreaID == a.ROWID || e.RegionID == r.ROWID // <--filters the data based on OR stmt
where s.StoreNum == 469
select new { r.RegionName, a.AreaName, s.StoreNum, s.StoreName, t.JobCode, e.FirstName, e.LastName }
Try this:-
var result= tableA.SelectMany(a => tableB.Where(x => x.A == a.A || x.B == a.B), (a, b) => new {a, b});

Conditional Join In LINQ?

I am trying to write a query that grabs information from one database and joins it to information in a different database.
TableA
idA
valueA
idB
TableB
idB
valueB
The tricky part is that in TableA, idB isn't always defined, so when I do a normal join, I only get results where TableA has a idB value. What I want is to be able to grab all of the information from TableA even if it doesn't have a corresponding idB value.
Here is a query expression syntax version of the left join to follow up on tvanfosson's answer.
var query = from rowA in db.TableA
join rowB in db.TableB
on rowA.idB equals rowB.idB into b
from item in b.DefaultIfEmpty()
select new
{
idA = rowA.idA,
valueA = rowA.valueA,
idB = rowA.idB,
valueB = item != null ? item.valueB : 0 // or other default value
};
Use a left outer join by checking if the value returned from the right hand side is null and supplying a default value for that case.
var q = db.TableA.Join( db.TableA,
a => a.idB,
b => b.idB,
(a,b) => new
{
A = a.ValueA,
B = b == null ? null : b.ValueB
});
You can do a left outer join in LINQ with SelectMany (directly calling Queryable methods) or in comprehension syntax join ... into:
var results = from a in db.TableA
join b in db.TableB on a.idB equals b.idB
into found
select new {
A = a,
Bs = found
};
In the output Bs will be IEnumerable<typeof-db-TableB>
Left Join Example:
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product{Name = String.Empty, CategoryID = 0})
select new { CatName = category.Name, ProdName = item.Name };

Categories

Resources