How to do this Linq-to-Sql join? - c#

Please do not give me help in lamba
I have two tables.
Employees:
pk
name
ExpenseTeamMembers:
pk
expMgrPk
empPk
Example: pk expMgrPk empPk
1 7 81
2 7 101
3 13 99
4 13 22
5 13 56
Basically the first table is a list of employees and the second is a table for keeping track of which employees belong to which manager.
The first sql lookup works and mgr is getting me the pk of the selected name in the combo box.
What I am trying to do in the join is lookup the expMgrPk and see which employees belong to it and return their names instead of their pk. I am pretty off and need a little help. Again please do not give me help in lamba!! Thanks
private void cboManagers_SelectedIndexChanged(object sender, EventArgs e)
{
if (cboManagers != null)
{
string selectedMgr = (string)cboManagers.SelectedValue;
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
int mgr = (from f in db.employees
where f.name == selectedMgr
select f.pk).FirstOrDefault();
var emps = (from m in db.employees
join t in db.expenseTeamMembers on m.pk equals t.pK
where t.expMgrPk == mgr
select m.name).ToList();
lstSelected.DataSource = emps;
}
}
}

In linq-to-sql, you can write joins more easily by writing two from statements combined with a where statement. Something like this:
var emps = (from f in db.employees
from m in db.expenseTeamMembers
where m.pk == mgr && f.pk == m.empPk
select f.name).ToList();
I've found this syntax to be easier and when your code is compiled, the query is converted to a traditional T-SQL join.

Related

Left/outer join with linq on c# with where condition clause

I have 2 tables that I need to join in a query.
The first table is the Entries table which contain certain events such as Dance, Speak, Sing, Play, etc.
Id|Name
1|Dance
2|Sing
3|Speak
4|Play
5| etc.
The other table contains userEntries which indicates each user's score on each of the events
Id| UserId|EntryId|Score
1|898128 | 1 |200
2|827329 | 2 |120
3|898128 | 2 |100
Now I want a linq query to first of all get all the entries and then get the scores for a given user for the entries retunining null for the entry score whete the user has noscore
Example
for user 898128, I want to see something like this
Dance:200,Speak:null,Sing:120 from the result
I have tried the following linq query and I get an empty result
var userScores =
(from e in db.Entries join se in db.UserEntries
on e.Id equals se.EntryId
into ese from se in
ese.DefaultIfEmpty()
where se.UserId == "898128"
select new
{
EntryLabel=e.Label,
EntryValue=se.ValueAmount,
}).ToList();
ViewData["userScores "] = userScores;
I am running on ASP.NET core 2.0, entity framework core on a Windows 10 machine with Visual Studio 2017 15.6.3
I will appreciate any guide to getting the query right to give me an outer join so I can get all the entries for each user even where the user does not have any score.
Please note that this is different from this question errorneously marked by #Mahmoud as its duplicate. The difference lies in the presence of the WHERE condition clause.
Thank you
Try this query. it should fix your issue.
var userScores =(from e in db.Entries
join se in db.UserEntries on e.Id equals se.EntryId into ese
from nullse in ese.DefaultIfEmpty()
where (nullse==nulll ||(nullse!=null && nullse.UserId == "898128"))
select new
{
EntryLabel = e.Name,
EntryValue = nullse != null ? nullse.ValueAmount:"null"
}).ToList();
I have found the answer from this SO question. From there, I realized that the position of the where clause is the problem. See the working code revision below
var userScores =
(from e in db.Entries join se in db.UserEntries.Where(o => o.UserId ==
"898128"
on e.Id equals se.EntryId
into ese from se in
ese.DefaultIfEmpty()
select new
{
EntryLabel=e.Label,
EntryValue=se.ValueAmount,
}).ToList();
ViewData["userScores "] = userScores;
Thank you #Hazarath for your guide

Access data from indirect child table using LInq

I have following table in my database and im accessing them through EF.
TestPack { id, name, type }
Sheets{ id, tp_id, date, rev }
Spool { id, sheet_id, date, rev, fabricated, installed }
which means a test pack has 1-M sheets and each sheet has 1-M spools. I want to get count of total Spools in the Test Pack, and count of spools that are fabricated, count of spools that are installed.
How do I get that through Linq query?
if I understand you right,you would like to have something like this
(from tp in ctx.TestPack
join st in ctx.Sheets on st.tp_id equals tp.id
join sl in ctx.Spool on sl.steet_id equals st.id
where tp.id == testPackId //you can change or delete this condition
select new {
Total = sl.Count() ,
FabricatedSpools = sl.Count(x=>x.fabricated == true),
InstalledSpools = sl.Count(x=>x.installed == true)
}).FisrtOrDefault();
Or maybe
(from tp in ctx.TestPack
join st in ctx.Sheets on st.tp_id equals tp.id
join sl in ctx.Spool on sl.steet_id equals st.id
where tp.id == testPackId //you can change or delete this condition
select new {
Total = sl.Count() ,
FabricatedSpools = (from s in sl
where s.fabricated == true
select s.Count()),
InstalledSpools = (from i in sl
where i.installed== true
select i.Count()),
}).FisrtOrDefault();
Not sure what you exact models are like but see below.
var testPackID = 2;//assuming
//assuming your DbContext is ctx;
var totalSpools = ctx.Spools.Count(x => x.Sheets.tp_id == testPackID);
var fabricatedSpools = ctx.Spools.Count(x => x.Sheets.tp_id == testPackID && x.fabricated);
var installedSpools = ctx.Spools.Count(x => x.Sheets.tp_id == testPackID && x.installed);
Sample data and query
I had generated the queries in SQL Server and hope you can do in LINQ. if you want specifically in LINQ let me know.
And can you please clarify whether you want result in 3 or all the 3 results in one.
Hope this helps.
Thank you.

linq query using joins and aggregate functions

I want to write a linq query which retrieves the data in the following format.
Assume that there are two tables - Department and Employee
Department
Dept_id| Manager_id
Employee
Emp_id| Dept_id| Emp_data
The relationship between Department and Employee table is one to many. The Department table also stores the manager employee id in that particular department. So Manager_id is nothing but the employee_id.
Now I want to get the data as follows
Dept_id, Manager_id, Emp_data(data of Manager_id), Count(employees in that department)
If I do the join on two tables i can get data of Manager but unable to get the count of all employees in that department. Any help would be appreciated.
You could do something like this:
var result=
(
from dep in db.Department
join emp in db.Employee
on dep.Manager_id equals emp.Emp_id
select new
{
dep.Dept_id,
emp,
NumberOfEmp= db.Employee.Count(c=>c.Dept_id==dep.Dept_id)
}
).ToList();
Where db is the linq data context
You could do a group join. If you have a preferred handcoded SQL statement that you would like to be generated from your LINQ query. You may want to experiment a bit with different formats to see which one allows you to generate the "best" SQL.
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = g.Single(x => x.emp_id == d.manager_id).emp_data,
employee_count = g.Count()
};
or
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
from m in g where m.emp_id == d.manager_id
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = m.emp_data,
employee_count = g.Count()
};

Remove certain records from a set of records using LINQ

Question - how to remove certain records from LINQ, like i have some records i wanted them to be removed from my LINQ.
Scenario - i have table A with 10 records and table B with 2 records i want to remove records that are belong to B to be removed from A [using linq]
-below i have all the records in q and i want to remove the records that are there in p.
var p = from c in q
join dr in dc.TableData on c.Id equals dr.CaseId
select new View()
{
ActiveCaseId = c.ActiveCaseId,
Id = c.Id
};
q = q.Except(p);
You can't do it with the Except as you show, because p and q are different types. But it would also be a bit clumsy.
You can do it in one query:
var p = from c in q
where !dc.TableData.Any(dr => dr.CaseId == c.Id)
select new View()
{
ActiveCaseId = c.ActiveCaseId,
Id = c.Id
};

LINQ to SQL Query for Many-to-Many relationship

I am moving an old ASP.net (C#) application from plain SQL queries to LINQ to SQL and am having some trouble with some of the more complex queries. In this case, I am trying to get a list of employees who have a certain set of skills. The user picks the skills to search for and the id's are supplied to the method that does the work. In the old SQL version, I just appended WHERE clauses to the string for each skill. Here's an example query:
SELECT DISTINCT e.firstname, e.lastname, e.username
FROM employees AS e
WHERE e.id IN (SELECT es.emp_id
FROM emp_skl AS es
WHERE es.skl_id = 6 OR es.skl_id = 11
GROUP BY es.emp_id
HAVING COUNT(es.emp_id) >= 2)
The key is the HAVING COUNT clause since that ensures the employees returned have ALL the skills and not just one. Anyway, can someone help me turn this into a solid LINQ query?
First of all, it's better if your tables don't end with an "S".
Now the code, asuming you have already a function yo get a list of skills:
IQueryable<skills> listSkills = getSkills();
IQueryable<employees> listEmployees = db.employees;
foreach(var skill in listSkills)
{
listEmployees=listEmployees
.Where(p=>p.emp_skls.Any(q=>q.skl_id==skill.id));
}
Edit:
for instance:
public IQueyable<skills> getSkills()
{
return db.skills.Where(p=>p.id==6 || p.id==1);
}
Here's the LINQ translation of your SQL query:
from e in Employees
where e.Emp_Skls.Count (es => es.Skl_id == 6 || es.skl_id == 11) >= 2
select new
{
e.FirstName, e.LastName, e.UserName
}
However, if your desired query is "give me employees who have both skills 6 and 11", your SQL query will fail if skill 6 or 11 appears twice for an employee (I take it this is possible because you have >= 2 rather than =2 in your having clause). In which case, the following query is a better fit:
from e in Employees
where e.Emp_Skls.Any (es => es.Skl_id == 6) &&
e.Emp_Skls.Any (es => es.Skl_id == 11)
select new
{
e.FirstName, e.LastName, e.UserName
}

Categories

Resources