retrieving using linq query and entityframework - linq

I have table structure like below
Employee Table
ID Name
1 A
2 B
3 C
4 D
5 E
Employee allocation table
Alocationid ID Date
1 2 26/6/2013
2 2 25/6/2013
3 1 25/6/2013
4 1 24/6/2013
5 3 24/6/2013
6 4 26/6/2013
Now i need to get the available employees for a particular date.for example if i need available employees for 25/6/2013 then the result would be like below:-
ID Name
1 A
3 C
4 D

101 Linq is a good reference site and this sample seems most appropriate to your situation.

If you are working with repositories and want a less query like approach you could use the following:
IQueryable<int> allocatedEmployeeIds = AllocationRepository.DbSet.Where(x => x.Date == referenceDate).Select(x => x.ID);
List<Employee> allocatedEmployees = EmployeeRepository.DbSet.Where(x => allocatedEmployeeIds.Any(y => y == x.ID).ToList();
Edit: and if you want those not allocated it is just a matter of adding "!"
IQueryable<int> allocatedEmployeeIds = AllocationRepository.DbSet.Where(x => x.Date == referenceDate).Select(x => x.ID);
List<Employee> allocatedEmployees = EmployeeRepository.DbSet.Where(x => !allocatedEmployeeIds.Any(y => y == x.ID).ToList();

Use group joing to get allocations of each employee. Then select those employees, which don't have any allocations for particular date:
from e in db.Employees
join ea in db.EmployeeAllocations
on e.ID equals ea.ID into g
where !g.Any(x => x.Date == date)
select e

Related

Using Linq, how would one join two tables without a foreign key relationship between the two tables?

So let's say we have these two tables:
CARS
ID CAR_MODEL
11 Mustang
22 Camaro
33 F-150
PARTS
ID CAR_ID PART_NAME
1 11 Steering Wheel
2 22 Steering Wheel
3 22 Headlights
NOTE: there is no foreign key relationship in the database between the PARTS.CAR_ID and CARS.ID columns.
Without the foreign key, what sort of linq query would be used to obtain these results:
CARS
ID CAR_MODEL PART_NAME_LIST
11 Mustang Steering Wheel
22 Camaro Steering Wheel, Headlights
33 F-150 (null)
Environment: SQL Server 2014, linq-to-sql
edit: here is what I have so far, but this results in 4 rows in the results (2 for Camaro), instead of 3, and it does not include any parts.
from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID
select new{
ID = C.ID,
CAR_MODEL = C.CAR_MODEL,
PART_NAME_LIST = ???
}
Here is a fluent syntax group join:
var sub = (from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID into Pj
select new {
C.ID,
C.CAR_MODEL,
PART_NAMES = from p in Pj select p.PART_NAME
})
.AsEnumerable();
var ans = from icp in sub
select new {
icp.ID,
icp.CAR_MODEL,
PART_NAME_LIST = String.Join(", ", icp.PART_NAMES)
I would probably switch to lambda syntax in the select in my code:
var ans = (from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID into Pj
select new {
C.ID,
C.CAR_MODEL,
PART_NAMES = Pj.Select(cpj => cpj.PART_NAME)
})
.AsEnumerable()
.Select(icp => new {
icp.ID,
icp.CAR_MODEL,
PART_NAME_LIST = String.Join(", ", icp.PART_NAMES)
});
For concatenating strings you have to use string.Join. The easiest way to do that is in a subquery:
(
from c in db.CARS
select new
{
ID = c.ID,
CAR_MODEL = c.CAR_MODEL,
PART_NAME_LIST = db.PARTS
.Where(p => c.ID equals p.CAR_ID)
.Select(p => p.PART_NAME)
}
).AsEnumerable()
.Select(c => new
{
ID = c.ID,
CAR_MODEL = c.CAR_MODEL,
PART_NAME_LIST = string.Join(", ", cPART_NAME_LIST)
})
Entity Framework doesn't support string.Join, so you have to split the query in a part that EF can translate into SQL and a part that's executed in memory, separated by AsEnumerable().

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);
}

Retrieve records who one field is max

I have some records
id title date
1 aaa 2005
2 bbb 2003
3 aaa 2007
4 ccc 2005
5 ccc 2009
I need to query to retrieve records by Date is max
id title date
2 bbb 2003
3 aaa 2007
5 ccc 2009
Query:
select *
from Table
where Table.date = (SELECT Max(date)
FROM Table temp
WHERE temp.title = Document.title)
I have sql query but need Linq query for this action
Something like this should work (C#):
var results =
from x in db.table
group x by x.title into g
select g.OrderByDescending(x => x.date)
.First();
Now for proper paging you'd have to call Skip / Take on the entire query like this:
var results =
(from x in db.table
group x by x.title into g
select g.OrderByDescending(x => x.date)
.First())
.Skip(0)
.Take(10);
GroupBy title, order group enumeration by date descending, select first item. something like this:
db.EntityName.GroupBy( en => en.title ).Select( g => g.OrderByDescending( en => en.date ).First() )

LINQ distinct on 2 fields

I have a LINQ query that returns data and I want to filter based on 2 fields (fkProfileID and fkOrgID) that are often the same. I only want to show 1 record when fkProfileID and fkOrgID match, so it is similar to doing an SQL distinct, but on 2 fields rather than one.
My data will look like this (other fields have been removed) :
fkProfileID fkOrgID
1 1001
1 1001
1 1001
2 1001
2 1001
1 1005
1 1005
So here I want to return only the following:
fkProfileID fkOrgID
1 1001
2 1001
1 1005
Here is my current LINQ (both fields above are in tblUserRights), how do I need to change it to do this?
List<ProfileJSON> lstProfiles = (from r in _database.tblUserRights
join p in _database.LuProfiles on r.fkProfileID equals p.luProfileID
join o in _database.tblOrganisations on r.fkOrgID equals o.pkOrgID
where r.fkUniqueID == intPKUserID
orderby o.OrgDesc, p.ProfileName
select new ProfileJSON
{
SiteID = o.pkOrgID,
SiteName = o.OrgDesc,
ProfileID = p.luProfileID,
ProfileName = p.ProfileName
}).ToList();
You can use .Distinct() after your query
List<ProfileJSON> lstProfiles = (from r in _database.tblUserRights
join p in _database.LuProfiles on r.fkProfileID equals p.luProfileID
join o in _database.tblOrganisations on r.fkOrgID equals o.pkOrgID
where r.fkUniqueID == intPKUserID
orderby o.OrgDesc, p.ProfileName
select new ProfileJSON
{
SiteID = o.pkOrgID,
SiteName = o.OrgDesc,
ProfileID = p.luProfileID,
ProfileName = p.ProfileName
}).Distinct().ToList(); //Distinct here

How to get the last element by date of each "type" in LINQ or TSQL

Imagine to have a table defined as
CREATE TABLE [dbo].[Price](
[ID] [int] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Price] [int] NOT NULL
)
where ID is the identifier of an action having a certain Price. This price can be updated if necessary by adding a new line with the same ID, different Price, and a more recent date.
So with a set of a data like
ID StartDate Price
1 01/01/2009 10
1 01/01/2010 20
2 01/01/2009 10
2 01/01/2010 20
How to obtain a set like the following?
1 01/01/2010 20
2 01/01/2010 20
In SQL, there are several ways to say it. Here's one that uses a subquery:
SELECT *
FROM Price p
WHERE NOT EXISTS (
SELECT *
FROM Price
WHERE ID = p.ID
AND StartDate > p.StartDate
)
This translates fairly trivially to LINQ:
var q = from p in ctx.Price
where !(from pp in ctx.Price
where pp.ID == p.ID
&& pp.StartDate > p.StartDate
select pp
).Any()
select p;
Or should I say, I think it does. I'm not in front VS right now, so I can't verify that this is correct, or that LINQ will be able to convert it to SQL.
Minor quibble: Don't use the name ID to store a non-unique value (the type, in this case). It's confusing.
Assuming ID & StartDate will be unique:
SELECT p.ID, p.StartDate, p.Price
FROM Price p
JOIN
(
SELECT ID, MAX(StartDate) AS LatestDate
FROM Price
GROUP BY ID
) p2 ON p.ID = p2.ID AND p.StartDate = p2.LatestDate
Since you tagged your question with LINQ to SQL, here is an LINQ query to express what you want:
from price in db.Prices
group price by price.Id into group
let maxDateInGroup = group.Max(g => g.StartDate)
let maxDatePrice = group.First(g => g.StartDate == maxDateInGroup)
select
{
Id = group.Key,
StartDate = maxDatePrice.StartDate,
Price = maxDatePrice.Price
};

Resources