Join multilevel relationship in LINQ to SQL - c#

There are 3 tables: ParentCategories -> Categories -> Articles.
ParentCategory(ID, Name)
Category(ID, parentCategoryID, Name)
Article(ID, caregoryID, Name)
How do I select all articles with specified parentCategoryID (the table articles has only reference to categoreID, not to ParentCategoryID) using LINQ to SQL?
Something like this:
articles = (
from a in db.Articles
join c in db.Categories
on ????????????
join pc in db.ParentCategories
on c.ParentCategoryId equals pc.ID
...);

(If I understand your schema correctly) you could use an implicit join strategy like:
var articles = db.Categories
.Where(c => c.ParentCategoryID == yourParentCategoryID)
.SelectMany(c => c.Articles)
.ToList();
The implicit join requires that you have Associations set up between your entities in your O/R designer.

articles = from a in db.Articles
join c in db.Categories
on myParentCategoryID equals c.ParentCategoryId
select a;

Related

SQL to Linq Lambda

Does anybody know how to convert this on outerjoin on LINQ Lambda?
I wan to achieve this using lambda linq
SELECT * FROM Posts as A LEFT JOIN Reactions as B on A.Id = B.PostId AND #userId = b.userid
Here is my current linq code
return await _dbContext.Posts
.GroupJoin(_dbContext.Reactions,
post => post.Id, reaction => reaction.PostId,
(post, reactions) => new { post, reactions })
.SelectMany(x => x.reactions.DefaultIfEmpty(),
(post, reaction) => new { post.post, reaction })
What you want to accomplish can be done in two different ways in SQL, and those ways can be translated to Linq.
Depending on your scenario (volume of data, indexes, etc) you may want to need one or another
Option A: Join the filtered data
SELECT a.Name, b.*
FROM
tableA
LEFT JOIN tableB on
b.Action='delete' AND a.Id = b.Id
would be translated in LINQ to something similar to:
var query =
from a in db.TableA
join pet in db.TableB.Where(x => x.Action=="delete") on a equals b.TableA into gj
from leftJoined in gj.DefaultIfEmpty()
and using method syntax:
var query = tableA
.GroupJoin(
tableB.Where(x => x.Action == "delete"),
tableA => tableA,
tableB => tableB.tableA,
(tableA, tableBs) => new {tableA, tableBs}
).SelectMany(x => x.tableBs.DefaultIfEmpty())
Option B: Do the join and later filter the data
SELECT a.Name, b.*
FROM
tableA
LEFT JOIN tableB on a.Id = b.Id
WHERE
b.Id = NULL OR b.Action='delete'
would be translated to:
var query =
from a in db.TableA
join pet in db.TableB on a equals b.TableA into gj
from leftJoined in gj.DefaultIfEmpty()
where lefjoined == null || leftjoined.Action == "delete"
A left outer join is a join in which each element of the first collection is returned, regardless of whether it has any correlated elements in the second collection. You can use LINQ to perform a left outer join by calling the DefaultIfEmpty method on the results of a group join.
You can use this approach
Query Syntax:
var query = (from post in Posts
join reaction in Reactions
on post.Id equals reaction.PostId
into reaction
from reaction in reaction.DefaultIfEmpty()
select new
{
post.Id,
//prod.Foo1,
//post.Foo2,
//reaction.Foo3,
//reaction.Foo4,
//you can select other fields too
}).OrderBy(ps => ps.Id);
For more information visit Perform left outer joins
Normally you don't. Flattening out related data like that is simply not necessary in LINQ. Just fetch the data with its natural shape:
_dbContext.Posts.Include(p => p.Reactions)
This returns the Posts and any reactions, without having to repeat the Post data for each Reaction, or having nulls for Posts without Reactions.

Join in LINQ and Entity Framework

In SQL I to get the distinct statement, I used join to get it as below
select distinct
col1
from
table1 a
inner join
table2 b on a.code = b.vcode
How can the same be implemented in LINQ over Entity Framework?
Please suggest me.
You can also use method syntax:
var query = table1.Join(table2,
a => a.code,
b => b.vcode,
(a,b) => a.col1)
.Distinct();
var result = (from a in table1
join b in table2 on a.code equals b.vcode
select a.col1).Distinct();

Linq one-to-many Union

I'm developing a MVC web application using asp.net C# and VS2012 Express.
I have a table (Organizations) with one-to-many relationships with two other tables (Comments and Proposals). All three tables contain an OrganizationID field to maintain the relationships. All three tables have an AddedBy string field.
I want to find all Organizations where either the Organization.AddedBy="Joe" or Comments.AddedBy="Joe" or Proposals.AddedBy="Joe".
These queries do a join, but I'm looking for a union that contains only the Organizations' fields.
// Find organizations created by this person.
IQueryable<Organization> org = from m in context.Organizations
where m.AddedBy.Equals("Joe")
select m;
// Find Comments created by this person.
IQueryable<Comment> comment = from m in context.Comments
where m.AddedBy.Equals("Joe")
select m;
// Join our two queries.
IQueryable<Comment> organizations = (from item in org
join c in comment on item.OrganizationID equals c.OrganizationID
select item).Distinct();
// Find Proposals created by this person.
IQueryable<Proposal> proposal = from m in context.Proposals
where m.AddedBy.Equals("Joe")
select m;
// Join our two queries.
organizations = (from item in organizations
join c in proposal on item.OrganizationID equals c.OrganizationID
select item).Distinct();
Thanks for your help.
If you are using Entity Framework you can do either:
var orgs = context.Organizations
.Where(O => O.AddedBy.Equals("Joe") ||
O.Comments.Any(C => C.AddedBy.Equals("joe")) ||
O.Proposals.Any(P => P.AddedBy.Equals("joe")));
As EF maintaining the parent-child relationship with navigation properties.
Hope this will help !!
So you're looking for three different sets, all combined. Just query each of those three things and then combine them using Union:
string user = "Joe";
var addedOrganizations = context.Organizations.Where(org => org.AddedBy == user);
var orgsWithUsersComments = from org in context.Organizations
join c in context.Comments
on org.OrganizationID equals c.OrganizationID
where c.AddedBy == user
select org;
var orgsWithUsersProposals = from org in context.Organizations
join p in context.Proposals
where p.AddedBy == user
select org;
var combinedResults = addedOrganizations.Union(orgsWithUsersComments)
.Union(orgsWithUsersProposals);

Entity Framework Query for inner join

What would be the query for:
select s.* from Service s
inner join ServiceAssignment sa on sa.ServiceId = s.Id
where sa.LocationId = 1
in entity framework?
This is what I wrote:
var serv = (from s in db.Services
join sl in Location on s.id equals sl.id
where sl.id = s.id
select s).ToList();
but it's wrong. Can some one guide me to the path?
from s in db.Services
join sa in db.ServiceAssignments on s.Id equals sa.ServiceId
where sa.LocationId == 1
select s
Where db is your DbContext. Generated query will look like (sample for EF6):
SELECT [Extent1].[Id] AS [Id]
-- other fields from Services table
FROM [dbo].[Services] AS [Extent1]
INNER JOIN [dbo].[ServiceAssignments] AS [Extent2]
ON [Extent1].[Id] = [Extent2].[ServiceId]
WHERE [Extent2].[LocationId] = 1
In case anyone's interested in the Method syntax, if you have a navigation property, it's way easy:
db.Services.Where(s=>s.ServiceAssignment.LocationId == 1);
If you don't, unless there's some Join() override I'm unaware of, I think it looks pretty gnarly (and I'm a Method syntax purist):
db.Services.Join(db.ServiceAssignments,
s => s.Id,
sa => sa.ServiceId,
(s, sa) => new {service = s, asgnmt = sa})
.Where(ssa => ssa.asgnmt.LocationId == 1)
.Select(ssa => ssa.service);
You could use a navigation property if its available. It produces an inner join in the SQL.
from s in db.Services
where s.ServiceAssignment.LocationId == 1
select s

How to convert this SQL query to LINQ to Entities query?

I need help to convert a SQL query to entity query in my C# code.
The query combines 4 different tables together which is as follows:
SELECT a.email,
a.status,
a.createdat,
b.unitprice,
c.name,
d.name,
e.name
FROM Orders a,
Orderdetails b,
ServiceOptions c,
services d,
merchants e
WHERE a.id=b.orderid AND c.id=b.serviceoptionid
AND c.serviceid=d.id AND d.merchantid=e.id
var query = from a in context.Orders
join b in context.OrderDetails on a.id equals b.orderid
join c in context.ServiceOptions on b.serviceoptionid equals c.id
join d in context.services on c.serviceid equals d.id
join e in context.merchants on d.merchantid equals e.id
select new { a.email,
a.status,
a.createdat,
b.unitprice,
c.name,
d.name,
e.name };
I think you are going the opposite direction. Create a entity framework first and then use LINQ from the EF to create the SQL. It should be EF->LINQ-SQL. The whole idea of EF is the user doesn't have to create a sql. This query can be done in LINQ to SQL after EF is created in the project.

Categories