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

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;

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 Row with Max date per group

I want to return all the values from my "Categories" table and join that to my "CategorySelections" table to display all the categories and whether the specified user selected them or not.
A complication (which I don't know how to deal with in LINQ) is that the user could have changed his selection/deselection of a particular category over time...each change would have logged in the "CategorySelections" table with a date stamp.
I am after the last selection status.
The following SQL query does what I want:
SELECT cs.UserId, c.CategoryId, m.MaxDate, cs.IsSelected
FROM [myDB].[dbo].[Categories] c
LEFT JOIN [myDB].[dbo].[CategorySelections] cs
ON c.CategoryID = cs.CategoryID AND cs.UserID = 7
INNER JOIN
(
SELECT UserId, CategoryId, Max(CreatedOn) as MaxDate
FROM [myDB].[dbo].[CategorySelections]
GROUP BY UserId, CategoryId
) m
ON cs.UserID = m.UserID AND cs.CategoryID = m.CategoryID AND cs.CreatedOn = m.MaxDate
ORDER BY cs.CategoryI
I need some help getting this done in LINQ.
Below is my attempt, which returns all the selections instead of just the last per category.
var query = from c in db.Category
join cs in db.CategorySelection.Where(x => x.UserID == WebSecurity.CurrentUserId)
on c.CategoryID equals cs.CategoryID into JoinedCategory
from cs in JoinedCategory.DefaultIfEmpty()
select new Selection() { CategoryID = c.CategoryID, CategoryName = c.CategoryName ,IsSelected = cs != null ? cs.IsSelected : false }
I am working in MVC; the "new Selection()" refers to my Model
You may add WHERE statement:
where cs.CreatedOn == CategorySelections.Where(t => t.CategoryId == cs.CategoryId).Max(r => r.CreatedOn)

How to join two tables and make group by in Linq

I have a question about Linq select statement. I am new to Linq so any help will be very helpful. I did a lot of research but I still didn't manage to write down correct Linq statement.
I have this two tables and attributes:
Table Titles(title_id(PK), title) and
Table Sales(title_id(PK), qty)
where are title_id and title string values and qty is a number which represents some quantity.
I need to write a select which will take five most selling titles from this two tables.
So, I need to make sum from qty (we can have more records with the same Sales.title_id attribute) and make group by title_id and order by sum(qty) descending and then return attributes title and title_id.
How can I make suitable solution for my question?
Regards,
Dahakka
You can do group join of tables by title_id (each group g will represent all sales of joined title). Then select title description and total of sales for that title. Order result by totals, select title and take required number of top sales titles:
var query = (from t in db.Titles
join s in db.Sales on t.title_id equals s.title_id into g
select new { Title = t.title, Total = g.Sum(x => x.qty) } into ts
orderby ts.Total descending
select ts.Title).Take(5);
Resulting SQL will look like:
SELECT TOP (5) [t2].[title] AS [Title], [t2].[value] AS [Total]
FROM (
SELECT [t0].[title_id], (
SELECT SUM([t1].[qty])
FROM [Sales] AS [t1]
WHERE [t0].[title_id] = [t1].[title_id]
) AS [value]
FROM [Titles] AS [t0]
) AS [t2]
ORDER BY [t2].[value] DESC
Following is the linq query in method syntax
sales.GroupBy(s=>s.title_id)
.Select ( x =>
new {
Title_id = x.Key,
Sales= x.Sum (x=> x.qty)
})
.OrderByDescending(x=>x.Sales).Take(5)
.Join( titles,
sale=>sale.Title_id,
title=> title.title_id,
(sale, title)=> new
{
Title = title.Title,
TotalSales=sale.Sales
}
);

Linq query, return distinct on single field & returning subset of data

I have a Linq query that returns three data elements.
var billingDateResults = from s in Subscriptions
.Where(s => (s.ProductCode.Contains("myCode")))
select { g.ID, BillingDate =s.BILL_THRU, s.ProductCode};
I would like to do distinct type of query on this to limit the results to one record per ID.
var billingDateResults = from s in Subscriptions
.Where(s => (s.ProductCode.Contains("myCode")))
group s by s.ID into g
select g.FirstOrDefault();
This works but now returns all of the fields in the records and I would like to minimize the amount of data by limiting the results to only the 3 fields in the first example.
What is a good way to do this?
TIA
Group by those three fields then.
var billingDateResults =
from s in Subscriptions
where s.ProductCode.Contains("myCode")
group new
{
g.ID,
BillingDate = s.BILL_THRU,
s.ProductCode
} by s.ID into g
select g.First(); // FirstOrDefault is not necessary, the groups will be non-empty

How do I select a person only if their Id appears in another table?

In the following LINQ statement, I'm trying to select people but only if their Id appears in another table (a join table). What am I missing?
In this example, I have a People table and a Contractors table. The Person's contactId may appear in the Contractors table. I want to grab the contactId of People that appear in the Contractors table.
var allPeople = People.Where(x => x.Contractors
.Where(m=> m.ContactID == x.ContactID)
.Select(x => x.ContactID));
How about regular LINQ JOIN statement:
var peopleWithContact = People.Join(
Contractors,
p => p.ContactId, // the field to join by from People table
c => c.ContactId, // the field to join by from Contractors table
(p, c) => p.ContactId); // the result if match; could be just p.
The Where function must return a boolean expression. If I understand your question correctly, you only want people from the peoples table that are in the contractors table as well. Then we can ask just that: Give me a person if any contractor has that ID:
var allPeople = People.Where(x => x.Contractors
.Any(m => m.ContactID == x.ContactID));

Resources