SQL query with JOIN to LINQ - c#

I'm having trouble translating following query to Linq:
SELECT u.UserId,
u.UserName,
r.RoleName
FROM aspnet_users u
INNER JOIN aspnet_UsersInRoles ur ON u.UserId = ur.UserId
INNER JOIN aspnet_Roles r ON r.RoleId = ur.RoleId AND
r.RoleName IN ('SuperAdmin', 'AdminExtended', 'ExpertExtended')
ORDER BY u.UserName
I've tried with several Linq queries but I'm not sure how to build the Roles <-> Users relation so I can get the role from each user, EF creates a Mapping between them using the aspnet_UsersInRoles table
Here's what I've tried:
var query = from u in context.aspnet_Users
from r in u.aspnet_Roles
where r.RoleName == "SuperAdmin" || r.RoleName == "AdminExtended" || r.RoleName == "ExpertExtended"
select u;
And
var query = from u in context.aspnet_Users
where u.aspnet_Roles.Any(r => r.RoleName == "SuperAdmin" || r.RoleName == "AdminExtended" || r.RoleName == "ExpertExtended")
select u;

Based on EF generating a join table aspnet_UsersInRoles and some of the field names you mention in your desired, generated, SQL query, I assume POCOs similar to the following (the remainder of this answer is dependent on these assumptions):
public class User
{
public int UserId { get; set; } // just assuming int key ID
public string UserName { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string RoleName { get; set; }
public virtual ICollection<User> Users { get; set; }
}
With this setup, you should be able to get the SQL output you're looking for with the following:
from r in context.Roles
where r.RoleName == "SuperAdmin" || r.RoleName == "AdminExtended" || r.RoleName == "ExpertExtended"
from u in r.Users
orderby u.UserName
select new {u.UserId, u.UserName, r.RoleName};
Notice EF and L2E does all the magic for you: it even infers the relations between the two POCOs from the relation names.
With just the code above, I dropped this into my compiler, set var q equal to the query shown, and dumped q.ToString() out - this is what I got:
SELECT
[Extent1].[RoleId] AS [RoleId],
[Join1].[UserId] AS [UserId],
[Join1].[UserName] AS [UserName],
[Extent1].[RoleName] AS [RoleName]
FROM [dbo].[Roles] AS [Extent1]
INNER JOIN (SELECT [Extent2].[Role_RoleId] AS [Role_RoleId], [Extent3].[UserId] AS [UserId], [Extent3].[UserName] AS [UserName]
FROM [dbo].[UserRoles] AS [Extent2]
INNER JOIN [dbo].[Users] AS [Extent3] ON [Extent3].[UserId] = [Extent2].[User_UserId] ) AS [Join1] ON [Extent1].[RoleId] = [Join1].Role_RoleId]
WHERE [Extent1].[RoleName] IN (N'SuperAdmin',N'AdminExtended',N'ExpertExtended')
ORDER BY [Join1].[UserName] ASC
I think this pretty much captures it.

try like following:
var roleNames = new List<string>(){"SuperAdmin","AdminExtended","ExpertExtended"};
from u in context.aspnet_Users
join uir in context.aspnet_UsersInRoles on u.UserId = uir.UserId
join r in context.aspnet_Roles on r.RoleId = uir.RoleId
where (roleNames.Contains(r.RoleName))
select new {UserId = u.UserId, UserName = u.UserName , RoleName = r.RoleName}
You can look more into detail about linq join query here on msdn documentation.

Same as Jenish, but if Roles is a navigation property of Users you can avoid a Join
from u in context.aspnet_Users
join r in context.aspnet_UsersInRoles on u.UserId equals r.UserId
select new {u.UserName, r.aspnet_Role.RoleName}
Nav Property aspnet_Role might have a different name IDK
You where close in your first attempt:
from u in context.aspnet_Users
from r in context.aspnet_UsersInRoles
where u.UserId == r.UserId
select new {u.UserName, r.aspnet_Role.RoleName}

Related

Linq join and group by together on multiple fields and truncate time in date

I have following Sql query which joins two table and group by date and user Id
User Table
UserName UserId
LookupScannedHistory
HistoryId UserId ScannedDate ScannedCount
I have written following sql query to join table and group by on userId and Scanned Date removing Time varaint
SELECT
l.[UserID]
,CAST([ScannedDate] AS DATE)
,Sum([ScannedCount])
,[UserName]
FROM [dbo].[LookupScannedHistory] l
Join [dbo].[UserMaster] u
on l.UserID = u.UserId
group by l.UserId, u.UserName, CAST([ScannedDate] AS DATE)
I want to convert this into linq.
I have tried this
(from log in dataContext.LookupScannedHistories
join user in dataContext.UserMasters
on log.UserID equals user.UserId
where log.ScannedDate >= fiveDayPriorDate
orderby log.ScannedDate
group log by new
{
ScannedDateOnly = EntityFunctions.TruncateTime(log.ScannedDate),
log.UserID
} into dateClickedHistory
select dateClickedHistory
).ToList();
I have done this this gives what I want but I am unable to include username by combining join and group by
I found the solution.
var usersReportGroupList = (from log in dataContext.LookupScannedHistories
join user in dataContext.UserMasters
on log.UserID equals user.UserId
where log.ScannedDate >= fiveDayPriorDate
orderby log.ScannedDate
group new { user.UserName, log.ScannedCount,
log.ScannedDate}
by new
{
ScannedDateOnly =
EntityFunctions.TruncateTime(log.ScannedDate),
log.UserID,
user.UserName
}
into dateClickedHistory
select dateClickedHistory
).ToList();
var usersReportList = new List<LookupScannedHistoryDetails>();
foreach (var group in usersReportGroupList)
{
usersReportList.Add(new LookupScannedHistoryDetails()
{
ScannedCount = group.Sum(x => x.ScannedCount.Value),
ScannedDate = group.Key.ScannedDateOnly.Value,
UserId = group.Key.UserID.Value,
UniqueCount = group.Count(),
UserName = group.Key.UserName
});
}

Sql server query equivalent in LINQ

I am trying to convert the following query in LINQ, tried different links but no luck so far. Please help with below:
SELECT T.TASKID,
T.TITLE,
T.DESCRIPTION,
T.DEADLINE,
T.CREATEDON,
(SELECT EMAIL FROM ASPNETUSERS WHERE ID = T.CREATEDBYUSERID) AS INITIATEDBY
FROM TBL_TASKMEMBERS AS M
INNER JOIN TBL_TASKS AS T ON M.TASKID = T.TASKID
INNER JOIN ASPNETUSERS AS U ON M.USERID = U.ID
WHERE m.UserId = '95d2f49c-0ae6-4571-9d7b-1c498ad0bfac'
Thanks in advance !
Try this:
var result =
from member in TBL_TASKMEMBERS
join task in TBL_TASKS on member.TASKID equals task.TASKID
join user in ASPNETUSERS on user.ID equals member.USERID
join usermail in ASPNETUSERS on usermail.ID equals task.CREATEDBYUSERID
where member.UserId = '95d2f49c-0ae6-4571-9d7b-1c498ad0bfac'
select new { TASKID = task.TASKID, TITLE = task.TITLE, DESCRIPTION = taks.DESCRIPTION, DEADLINE = task.DEADLINE, CREATEDON = task.CREATEDON, INITIATEDBY = usermail.EMAIL };

SQL to Linq Conversion Issue

Can someone help me convert a sql statement to linq? I can do very basic statement but I get confused when dealing with several joins and unions when using linq. Here is the SQL statement that I am trying to convert:
SELECT UserName, UPPER(FirstName) as FirstName, UPPER(LastName) as LastName
FROM PDDA.dbo.Users
WHERE Cono = " & Cono & "
UNION
SELECT u.UserName, UPPER(FirstName) as FirstName, UPPER(LastName) as LastName
FROM PDDA.dbo.GroupMembers g
JOIN PDDA.dbo.UserGroups ug
on ug.groupid = g.groupid
JOIN PDDA.dbo.Users u
on u.username = g.username
WHERE ug.GroupName = 'AP Department' OR ug.GroupName = 'MIS'
ORDER BY LastName, FirstName")
And here is my attempt so far:
var userDb = new PDDAEntities();
var users =
((from user in userDb.Users select user.UserName).Union(from gm in userDb.GroupMembers
join ug in userDb.UserGroups on gm.GroupID equals ug.GroupID
(from u in userDb.Users join ))
select user.UserName;
Break it down and it becomes easier. First step, the first part:
SELECT UserName, UPPER(FirstName) as FirstName, UPPER(LastName) as LastName
FROM PDDA.dbo.Users WHERE Cono = " & Cono & "
This is pretty easy.
var query1 = from u in Users where u.Cono == yourCono
select new { u.UserName, u.FirstName, u.LastName }
The second part is a little harder, but not much.
SELECT u.UserName, UPPER(FirstName) as FirstName, UPPER(LastName) as LastName
FROM PDDA.dbo.GroupMembers g
JOIN PDDA.dbo.UserGroups ug on ug.groupid = g.groupid
JOIN PDDA.dbo.Users u on u.username = g.username
WHERE ug.GroupName = 'AP Department' OR ug.GroupName = 'MIS'
ORDER BY LastName, FirstName
This would look something like this (not tested, but should be similar):
var query2 = from gm in GroupMembers
join ug in UserGroups on gm.groupid equals ug.groupid
join u in Users on gm.UserName equals u.UserName
where ug.GroupName == 'AP Department' || ug.GroupName == 'MIS'
orderby u.LastName, u.FirstName
select new { UserName = u.UserName, FirstName = u.FirstName, LastName = u.LastName }
Then just combine them.
var query3 = query1.Union(query2);
I'm not sure if the Order by orders the unioned set or not, if so, then you would just do this instead:
var query3 = query1.Union(query2).OrderBy(x => x.LastName).ThenBy(x => x.FirstName);
And you can remove the OrderBy from the query2 above.
EDIT:
Based on Striplings Query, you could probably even do this as well (assuming you have UserGroups navigation property configured):
from u in userDb.Users
where u.UserGroups.Any(ug => ug.GroupName == "AP Department" || ug.GroupName == "MIS")
|| u.Cono == yourCono
orderby u.LastName, u.FirstName
select new {u.UserName, u.FirstName, u.LastName}
No Union required at all then.
I find LINQ to be far more intuitive than SQL, and most people's difficulty with it arises from trying to do a direct translation rather than letting LINQ do the work for them. Assuming you've got your table relationships set up right, you can probably do something like this:
from u in userDb.Users
where u.UserGroups.Any(ug => ug.GroupName == "AP Department" || ug.GroupName == "MIS")
orderby u.LastName, u.FirstName
select new {u.UserName, u.FirstName, u.LastName};

Join two tables in Linq to SQL

Maybe a quite easy question but I'm new in Linq to SQL. I have two tables
User : UserId,name,Password,Email
USER_TABLE: Id, UserId, FirstName,LastName......
I would like a query that gives for example: userID=3 then give all the details (FirstName,LastName etc)
How can I join these two tables? I would prefer C# code if it is possible!
You do not have to do all the plumbing yourself. If you have the right foreign keys in the database you will not have to join yourself.
You can just do:
var query = from u in db.Users
select new { User = u;
FirstName = u.UserTables.FirstName }
for an inner join use something like:
var query = from u in db.Users
join ut in db.UserTables on u.UserId equals ut.UserId
select new
{
User = u,
Extra = ut
};
It's possible to join tables using linq:
E.g :
var test = (from a in DataContext.User
join b in DataContext.UserTable on a.UserId equals b.UserId
select new
{
UserId = a.UserId,
FirstName = b.FirstName
LastName = b.LastName
}).ToList();
Regards
Like this perhaps:
var joinedResult = from u in context.User
join u2 in context.UserTable on u.UserId equals u2.UserId
select new {
UserId = u.UserId,
FirstName = u2.FirstName
};
I guess your example is just an example, right? Cause it doesn't make much sense splitting that data into two tables.

Linq To SQL and Having

I am fairly new to Linq To SQL but trying to run what should be a fairly simple SQL query and can't figure out how to make it play nice in LINQ.
SELECT Users.Id, Users.Id AS Expr1, Users.FirstName, Users.LastName,
User_x_Territory.UserID
FROM Users LEFT OUTER JOIN
User_x_Territory ON User_x_Territory.UserID = Users.Id
GROUP BY Users.Id, Users.Id, Users.FirstName, Users.LastName, User_x_Territory.UserID
HAVING (COUNT(User_x_Territory.UserID) = 0)
Just trying to get all users that do not have a territory assigned, the only way to tell if they have a territory is to check the user_x_territory gerrund.
I am able to get all of the users out of my DB with this:
var users = from u in db.Users
join uXt in db.User_x_Territories on u equals uXt.User into gerr
from users in gerr.DefaultIfEmpty()
select users;
But from there I can't figure out how to add a group by/having to refine the search results to only show users with no territories.
Thanks for any help.
I suggest the following solution.
db.Users.Where(u => u.User_x_Territories.Count == 0)
edit: heh, guess someone beat me to it :(
from t in db.Users
join t0 in db.User_x_Territory on new { UserID = t.Id } equals new { UserID = t0.UserID } into t0_join
from t0 in t0_join.DefaultIfEmpty()
group new {t, t0} by new {
t.Id,
Column1 = t.Id,
t.FirstName,
t.LastName,
t0.UserID
} into g
where g.Count() == 0
select new {
Id = g.Key.Id,
Expr1 = g.Key.Id,
g.Key.FirstName,
g.Key.LastName,
UserID = g.Key.UserID
}
I don't know how efficient this is (I'm guessing not very), but you could try something like this:
var users = (from u in db.Users
join uXt in db.User_x_Territories on u equals uXt.User into gerr
from users in gerr.DefaultIfEmpty()
select u).Where(u => u.User_x_Territories.Count == 0);

Categories

Resources