lambda expression join multiple tables with select and where clause - c#

I have three table many to many relationship I have joined the three table and select the value I want but now I need to select one row from the query result by where by specifying the id this is my three table
And this is the query using LINQ lambda expression :
DataBaseContext db = new DataBaseContext();
public ActionResult Index()
{
var UserInRole = db.UserProfiles.
Join(db.UsersInRoles, u => u.UserId, uir => uir.UserId,
(u, uir) => new { u, uir }).
Join(db.Roles, r => r.uir.RoleId, ro => ro.RoleId, (r, ro) => new { r, ro })
.Select(m => new AddUserToRole
{
UserName = m.r.u.UserName,
RoleName = m.ro.RoleName
});
return View(UserInRole.ToList());
}
the result will be like that using sql query
sql query
select *
from UserProfile u join webpages_UsersInRoles uir on u.UserId = uir.UserId
join webpages_Roles r on uir.RoleId = r.RoleId
result of the sql query
now i use anther sql query to filter the result of previews sql query by where and set the condition to where u.UserId = 1 to only give me back the user with the id 1 like that
select *
from UserProfile u join webpages_UsersInRoles uir on u.UserId = uir.UserId
join webpages_Roles r on uir.RoleId = r.RoleId
where u.UserId = 1
and the result of this sql query
so how can i add the where clause to my lambda expression to give me the same result as the result of the sql query and thanks for any help

If I understand your questions correctly, all you need to do is add the .Where(m => m.r.u.UserId == 1):
var userInRole = db.UserProfiles.
Join(db.UsersInRoles, u => u.UserId, uir => uir.UserId,
(u, uir) => new { u, uir }).
Join(db.Roles, r => r.uir.RoleId, ro => ro.RoleId, (r, ro) => new { r, ro })
.Where(m => m.r.u.UserId == 1)
.Select (m => new AddUserToRole
{
UserName = m.r.u.UserName,
RoleName = m.ro.RoleName
});
Hope that helps.

I was looking for something and I found this post. I post this code that managed many-to-many relationships in case someone needs it.
var userInRole = db.UsersInRoles.Include(u => u.UserProfile).Include(u => u.Roles)
.Select (m => new
{
UserName = u.UserProfile.UserName,
RoleName = u.Roles.RoleName
});

Related

Entity Framework get all columns with group by

we are migrating reports from SQL to EF. In the process I just stumbled over the following query:
SELECT
pl.clientid,
pl.loginname,
COUNT(*)
FROM
(
SELECT
DISTINCT
s.clientid,
s.doctype
FROM
Specifications s
) A
INNER JOIN portal_logins pl ON A.clientid = pl.clientid
WHERE
A.clientid != '0'
GROUP BY
A.clientid,
A.doctype
My current solution is the following
return await _nfContext.Specifications
.Select( x => new
{
Clientid = x.Clientid,
Doctype = x.Doctype
})
.Distinct()
.Join(
_nfContext.PortalLogins,
s => s.Clientid,
p => p.Clientid,
(spec, login) => new
{
loginName = login.Loginname,
clientId = spec.Clientid,
doctype = spec.Doctype
}
)
.Where(x => x.clientId != "0")
.GroupBy(c => new
{
c.clientId,
c.doctype,
c.loginName
})
.Select(result => new TotalActiveConnections
{
ActiveConnections = result.Count(),
ClientId = result.Key.clientId,
LoginName = result.Key.loginName
})
.OrderByDescending(x => x.ActiveConnections)
.ToListAsync()
.ConfigureAwait(false);
My problem is, I need all three columns as described in the Group by, but I don't want to group by login name. Does anyone have an idea what I can do? Thanks in advance for the help....
You should just use Min or Max to get any random login value
.GroupBy(c => new
{
c.clientId,
c.doctype
})
.Select(result => new TotalActiveConnections
{
ActiveConnections = result.Count(),
ClientId = result.Key.clientId,
LoginName = result.Min(g => g.loginName),
})
Presumably it worked in SQL because you were using MySQL/MariaDB and did not have ONLY_FULL_GROUP_BY turned on.

Expression With and Union All to EF Core

I want to convert this SQL query to EF Core code.
I don't want to use LINQ, any possibility?
with cat (id, id_parent, name) as
(
select id, id_parent, name
from categories
where categories.id = 9
union all
select e.id, e.id_parent, e.name
from dbo.categories e
inner join brands b on b.id_parent = e.id
);
select * from cat;
If I get your question correctly this would work for you:
var result = await _dbContext.Categories
.Where(x => x.Id == 9)
.Select(x => new { Id = x.Id, Parent = x.IdParent, Name = x.Name})
.Concat(
_dbContext.Categories.Join(_dbContext.Brands, cat=> cat.Id, brand=> brand.IdParent, (cat,brand)=>cat)
.Select(x => new { Id = x.Id, Parent = x.IdParent, Name = x.Name }))
.ToListAsync();

Self Join or Inner Query in a table with Linq to SQL

I have two tables User & Employee.
+-------Supervisor----------+
SupervisorId
Password
+---------------------+
+-------Employee----------+
EmployeeId
EmployeeSupervisorId
EmployeeName
+---------------------+
This is what I am doing so far
SupervisorName = db.Employee.Where(m => m.EmployeeSupervisorId == m.SupervisorId).Select(q => q.EmployeeName).ToList()
I am not understanding the concept of how I join my Employee table to itself so that I can get a list of Employee and their corresponding Supervisor Name
You can do the below
SupervisorName = db.Employee
.Join(db.Supervisor,
emp => emp.EmployeeSupervisorId,
sup => sup.SupervisorId,
(emp, sup)=> new {SupervisorName = emp.EmployeeName})
.Select(x=>x)
.ToList();
SupervisorName = db.Employee.
Join(db.Supervisoer, e => e.EmployeeSupervisorId, s => s.SupervisorId, (e, s) => new { Employee = e, Supervisor = s}.
ToList().
Select(e => e.EmployeeName).
ToList();
You can use a simple subquery like this
var result = db.Employee.Select(e => new
{
Employee = e,
SupervisorName = db.Employee
.Where(s => s.EmployeeId == e.EmployeeSupervisorId)
.Select(s => s.EmployeeName).FirstOrDefault()
}).ToList();
Note that if you have EmployeeSupervisorId defined as a foreign-key pointing back to EmployeeId, the Linq2Sql will automatically create a EmployeeSupervisor property (which would be an Employee object)
var list = from e in db.Employee
// where e.......
select new {
Name = e.EmployeeName,
Supervisor = e.EmployeeSupervisor.EmployeeName,
// otherdetails = e......
}
If you haven't defined the foreign key, you have to specify it explicitly in the query:
var list = from e in db.Employee
join s in db.Employee on e.EmployeeSupervisorId equal s.EmployeeId
// where e.......
select new {
Name = e.EmployeeName,
Supervisor = s.EmployeeName,
// otherdetails = e......
}

Select inside select (SQL to lambda linq expression)

Select Label,
(SELECT COUNT(*) from [CourtSessions] cs where cs.iDCity = Cit.ID) as courts,
(Select COUNT(*) from [Cases] c inner join [CourtSessions] cs ON c.ID = cs.iDCase where cs.iDCity = Cit.ID) as csnatures
FROM Cities Cit
Group by Label, id
I tried this but it doesn't work
var data = db.Cities
.GroupBy(a => a.label)
.Select(g => new
{
city = g.Key,
sessions = db.CourtSessions.Include(p => p.CityTB).Count(o => o.CityTB.label == g.Key),
cases = db.Cases.Join(db.CourtSessions, u => u.ID, ui => ui.iDCase, (u, ui) => new { u, ui }).Count(m => m.ui.CityTB.label == g.Key)
});
Where CityTB is a foreign key
Cases (ID ...)
Cities (ID, Label)
CourtSession (ID, iDCase, iDCity ... CasesTB, CityTB)
I am getting this exception
base {System.Exception} = {"LINQ to Entities does not recognize the method 'System.Linq.IQueryable1[LawbookMVC.Models.CourtSession] Include[CourtSession,City](System.Linq.IQueryable1[LawbookMVC.Models.CourtSession], System.Linq.Expressions.Expression1[System.Func2[LawbookMVC.Mod...
Thanks.
Well i solved it, thanks you all
var dat = db.Cities
.GroupBy(a => new { a.label, a.ID})
.Select(g => new
{
city = g.Key.label,
sessions = db.CourtSessions.Count(o => o.iDCity == g.Key.ID),//,
cases = db.Cases.Join(db.CourtSessions, u => u.ID, ui => ui.iDCase, (u, ui) => new { u, ui }).Count(m => m.ui.CityTB.label == g.Key.label)
});

Joining two tables in linq method syntax, MVC EntityFramework

I'm working with two tables: CI_CLIENTRISK (SCD type 2)... and QB_INVOICES_HEADER (edmx screenshot).
They can be joined via ClientID. I want to essentially replicate this query:
SELECT a.ClientID,
MAX(b.InvoiceDt) AS MaxInvoiceDt
(omitted for brevity)
FROM CI_CLIENTRISKADJS a
INNER JOIN QB_INVOICES_HEADER b
ON a.ClientID = b.ClientID
WHERE a.IsActive = 1
GROUP BY a.ClientID
ORDER BY MaxInvoiceDt DESC
Here's what I have so far. It's not returning any records.
using (var db = new PLOGITENS01Entities())
{
var rvClientRiskAdjs = db.CI_CLIENTRISKADJS
.Take(50)
.Join(db.QB_INVOICES_HEADER,
a => a.ClientID,
b => b.ClientID,
(a, b) => new { Risk = a, Invoices = b })
.Where(a => a.Risk.IsActive == 1)
.OrderByDescending(o => o.Invoices.InvoiceDt)
.Select(c => new ClientRiskModel()
{
ClientRiskId = c.Risk.ClientRiskID,
ClientName = c.Risk.CI_CLIENTLIST.ClientName,
ClientId = c.Risk.ClientID,
ClientRiskAdjs = c.Risk.ClientRiskAdjs,
RecordValidStartDt = c.Risk.RecordValidStartDt,
RecordValidEnddt = c.Risk.RecordValidEnddt,
IsActive = c.Risk.IsActive
})
.ToList();
return View(new GridModel(rvClientRiskAdjs));
}
Try putting your .Take(50) method after your final .Select and before .ToList(). As it is, you are only taking the first 50 records of the first table and then joining from there. I'm assuming that there are no joins to the second table in the first 50 records of the first table; therefore, your result will have 0 records.
I stumbled across this solution from reading this post: https://stackoverflow.com/a/157919/1689144
var rvClientRiskAdjs = (from ri in db.CI_CLIENTRISKADJS
join qb in
(from qb in db.QB_INVOICES_HEADER
orderby qb.InvoiceDt ascending
group qb by qb.ClientID into grp
select new
{
InvoiceDt = grp.Max(s => s.InvoiceDt),
ClientID = grp.Key
})
on ri.ClientID equals qb.ClientID
orderby qb.InvoiceDt descending
where ri.IsActive == 1
select new ClientRiskModel()
{
ClientRiskId = ri.ClientRiskID,
ClientName = ri.CI_CLIENTLIST.ClientName,
ClientId = ri.ClientID,
ClientRiskAdjs = ri.ClientRiskAdjs,
RecordValidEnddt = ri.RecordValidEnddt,
RecordValidStartDt = ri.RecordValidStartDt
})
.ToList();

Categories

Resources