Convert SQL NOT IN query to LINQ to Entities - linq

I have two tables: User and UserRole.
I have the following SQL query to get all users who are NOT IN a certain role:
SELECT * FROM User
WHERE UserID NOT IN (SELECT UserID FROM UserRole WHERE RoleID = 32)
Assuming I have a User entity and a UserRole entity in my EF 5 model, how do I write a LINQ to Entities query to get the same results as the SQL query above?

you use something like:
repo.Users.Where(x => x.UserRoles.Where(y => y.RoleID == 32).Count() == 0)
or, according remarks :
repo.Users.Where(x => !x.UserRoles.Any(y => y.RoleID == 32))
or
repo.Users.Where(x => x.UserRoles.Count(y => y.RoleID == 32) == 0)
or
...

Related

Transform Sql to EF Core Linq query

I am trying to translate the following query from SQL to EF Core. I can easily just use a stored procedure (I already have the SQL), but am trying to learn how some of the linq queries work. Unfortunately this is not by any means an ideal database schema that I inherited and I don't have the time to convert it to something better.
DECLARE #userId INT = 3
SELECT *
FROM dbo.CardGamePairs
WHERE EXISTS (SELECT 1
FROM dbo.Users
WHERE Users.Id = CardGamePairs.player1Id
AND Users.userId = #userId)
UNION
SELECT *
FROM dbo.CardGamePairs
WHERE EXISTS (SELECT 1
FROM dbo.Users
WHERE Users.Id = TableB.player2Id
AND Users.userId = #userId)
So basically I have an id that can exist in one of two separate columns in table b and I don't know in which column it may be in, but I need all rows that have that ID in either column. The following is what I tried to make this work:
//Find data from table A where id matches (part of the subquery from above)
var userResults = _userRepository.GetAllAsQueryable(x => x.userId == userId).ToList();
//Get data from table b
var cardGamePairsResults = _cardGamePairsRepository.GetAllAsQueryable(x => userResults .Any(y => y.userId == x.player1Id || y.userId == x.player2Id));
When I run the code above I get this error message:
predicate: (y) => y.userId == x.player1Id || y.userId == x.player2Id))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().
Any ideas on how I can make this work? (I tried changing the column and table names to something that would actually make sense, hopefully I didn't miss any spots and make it more confusing.)
Because you are already have user id use it to query both columns.
var userResults = _userRepository
.GetAllAsQueryable(x => x.userId == userId)
.ToList();
var cardGamePairsResults = _cardGamePairsRepository
.GetAllAsQueryable(x => x.player1Id == userId || x.player2Id == userId));

Linq select a record based on child table data

Trying to select orders based on their current status which is stored in a another table. Keep getting all orders instead of orders filtered by current status. When status is not empty, the query should filter based on the latest status of the order which I think should be status in descending order of date of record taking the first status.
private IQueryable<order_tbl> CreateQuery(string status, int? orderId, DateTime? orderDate) {
var query = from o in context.order_tbl select o;
if (orderId.HasValue) query = query.Where(w => w.id.Equals(orderId.Value));
if (orderDate.HasValue) query = query.Where(w => w.OrderDate.Equals(orderDate.Value));
if (!string.IsNullOrEmpty(status)) {
query = (from q in query
from s in q.order_status
.OrderByDescending(o => o.DateStatusUpdated)
.Take(1)
.Where(w => w.Status.Equals(status))
select q);
}
return query;
}
There are more fields in the tables which I omitted for brevity.
order_tbl
id date customerId
1 2/1/2018 6
2 2/3/2018 5
3 2/6/2018 3
order_status
id orderId DateStatusUpdated status
1 1 2/1/2018 open
2 1 2/2/2018 filled
3 2 2/3/2018 open
4 2 2/4/2018 filled
5 3 2/6/2018 open
When searching only on 'open', the query will return orders 1,2,3 instead of just order 3. What is wrong with the query on the status?
This answer pointed me in the right direction, LINQ Query - Only get Order and MAX Date from Child Collection
Modified my query to the below.
if (!string.IsNullOrEmpty(status)) {
{
query = query
.SelectMany(s => s.order_status
.OrderByDescending(o => o.DateStatusUpdated)
.Take(1)
)
.Where(w => w.Status.Equals(status))
.Select(s => s.order_tbl);
}

linq to entities Not in statement

I am new to linq to entities. I am trying to do a not in statement and when i run it i am getting noting back. But if i run the SQL equivalent i get data back.
The SQL statement that i am trying to replicate is
SELECT * FROM [SCRAPREASON] WHERE [CODE] NOT IN (SELECT [CODE] FROM [QUALITYALERTRULE]) ORDER BY [CODE]
The Linq i have at the moment is
var DefectCode = PumaOEEEntities.ScrapReasons
.Where(x => !PumaOEEEntities.QualityAlertRules.Any(y => y.Code != x.Code))
.Select(x => new { GroupID = x.Code}).ToList();
Can anyone see what i am doing wrong?
You should compare codes for equality (== instead of !=):
var reasons = PumaOEEEntities.ScrapReasons
.Where(x => !PumaOEEEntities.QualityAlertRules.Any(y => y.Code == x.Code))
.OrderBy(x => x.Code)
.ToList();
Generated SQL will look like:
SELECT
[Extent1].[Code] AS [Code],
// Other columns
FROM [dbo].[ScrapReasons] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[QualityAlertRules] AS [Extent2]
WHERE [Extent2].[Code] = [Extent1].[Code]
)
ORDER BY [Extent1].[Code] ASC
You can try Except like this
var DefectCode = PumaOEEEntities.ScrapReasons.Select(x=>x.Code)
.Except(PumaOEEEntities.QualityAlertRules.Select(y=>y.Code)).ToList();

Sorting issue with LINQ query and join using tables from different databases

I'm having trouble writing my LINQ query.
Here's the scenario:
I have 2 databases: A and B
In database A: I have a tableX which has the following fields: Employee ID, Name, Address, Phone, ..., Active
In database B: I have a tableY which has the following fields: Employee ID, Visible, Order
the number of records in table Y is less than or equal to the number of records in table X.
Basically, I need to extract the employee records from table X who have the attribute 'Visible' (in table Y) set to True and would like to sort them using the 'Order' attribute.
This is what I have so far:
ADataContext dbA = new ADataContext();
BDataContext dbB = new BDataContext();
//Get the list of records from tableY where 'Visbile' is set to True
var List = dbB.tableY
.Where(x => x.Visible == true).OrderBy(x => x.Order)
.ToList();
//Extract the list of employee IDs
IEnumerable<int> ids = List.Select(x => x.EmployeeID).Distinct();
var employees = dbA.tableX
.Where(x => ids.Contains(x.EmployeeID) && x.Active == true)
.ToList();
I'm able to get the correct list of employees, but cannot figure out how to apply the sorting order (present in tableY) on tableX
Currently, regardless of the order specified in tableY, the records returned from tableX are sorted as they were entered in the table (oldest to most recent).
Any ideas how I can fix my query.
Thanks,
I've re-written it all as a single query:
var employees =
from x in dbA.tableX
where x.Active
from y in dbB.tableY
where x.EmployeeID == y.EmployeeID
orderby y.Order
select x;

orderby nested linq

var query = from m in db.Members.Include("Companies.Projects.Experiences.ExperienceTags")
where m.MemberId == id
select m;
I would like to also from this query to orderby the project.enddate. How would I do that. Also enddate can be null which then I would like it to be today date when it orderby. And, a company might not always have a project either which then it should be orderby today date too.
here is a image of the ef data diagram a link
Since there is a many relationship you need to do a SelectMany like so:
var query = from m in db.Members.Include("Companies.Projects.Experiences.ExperienceTags")
where m.MemberId == id
orderby m.Companies.SelectMany(c => c.Projects).OrderByDescending(p => p.EndDate).FirstOrDefault() == null ?
DateTime.Today :
m.Companies.SelectMany(c => c.Projects).OrderByDescending(p => p.EndDate).FirstOrDefault()
select m;

Resources