Linq to Sql Union statement - c#

I have two resultsets that I'm trying to union on (LINQ to SQL/Entity)
var ldrSet = (from ldr in Leader
join emp in employee
on ldr.ID equals emp.ID
where ldr.ID.Contains("123")
select new {ID = ldr.ID, Name = emp.firstName + " " + emp.lastName, flag = "Edit"});
var allEmpSet = (from emp in employee
where emp.ID.Contains("123")
select new {ID = ldr.ID, Name = emp.firstName + " " + emp.lastName, flag = "New"});
var results = ldrSet.Union(allEmpSet);
When I run this query I get something like this:
123 Joe Blow Edit
123 Joe Blow New
234 Jane Smith New
345 John Doe New
I understand why this is occurring but is there a way to further filter this resultset down by just using ID?
I want one record to return and the Edit record trumps the New record. So I just want this:
123 Joe Blow Edit
234 Jane Smith New
345 John Doe New

The proper way to handle things in this case isn't a Union. It's to use a left outer join instead of the inner join that LINQ defaults to. That will allow you to select all of the rows a single time and set the flag if data was matched appropriately:
var results = from e in employee
join l in leaders on l.ID equals e.ID into ls
from l in ls.DefaultIfEmpty()
select new {
e.ID,
Name = e.firstName + e.lastName,
flag = (p == null ? "New" : "Edit")
};

You can use GroupBy to group records by their ID and select just one of them:
var results = ldrSet.Union(allEmpSet)
.GroupBy(item => item.ID, (key, items) =>
items.OrderBy(item => item.flag)
.FirstOrDefault());
You can change the contents of OrderBy to determine which of the items to choose.

Related

need to get unmatched records from these 2 lists/tables using linq

Using these 2 tables:
employee(id, name)
payroll(name, salary)
I need to modify & convert this SQL query to linq:
SELECT employee.id, employee.name, payroll.salary
FROM employee left OUTER JOIN payroll
ON employee.name like payroll.name + '%'
to get unmatched records from those 2 tables. Any idea?
You can try this query:
var query = from emp in context.employee
join res in (from emp in context.employee
from pay in context.payroll
where emp.name.StartsWith(pay.name)
select new
{
emp.id,
pay.salary
})
on emp.id equals res.id into subRes
from sub in subRes.DefaultIfEmpty()
select new
{
emp.id,
emp.name,
sub?.salary
};

Not a simple Max

I have the following data:
Id | Value | OtherStuff
---------------------------
6 | 6 | 1
---------------------------
5 | 4 | 2
---------------------------
5 | 2 | 3
The desired result:
Id | Value | OtherStuff
---------------------------
6 | 6 | 1
---------------------------
5 | 4 | 2
That is I need the Max Value for each of the Id's.
I'm a bit stumped of how to do this without breaking it into multiple queries, can it be done, and if so how?
Update: I think I oversimplified the issue:
var query = from st in StockStakes
join o in Organisations on j.OrganisationId equals o.OrganisationId into oGroup
from o in oGroup.DefaultIfEmpty()
where st.Stock.Status == "A"
select new
{
Id = st.Id,
Value = st.Value,
CustomerId = o.OrganisationId
};
The data sample from above still stands... now how do i structure the query to give me the Max Value alongside each Id?
var query = from x in data
group x by x.Id into x
select x.OrderByDescending(y => y.Value).FirstOrDefault()
Based on you updated query, similar approach to the first query, but since you have multiple tables you need to group all the tables into an anonymous object and then select only the columns you want
var query = from st in StockStakes
join o in Organisations on j.OrganisationId equals o.OrganisationId into oGroup
from o in oGroup.DefaultIfEmpty()
where st.Stock.Status == "A"
group new { st, o } by st.Id into g
let largestValue = g.OrderByDescending(x => x.Value).FirstOrDefault()
select new
{
Id = g.Key,
Value = largestValue.st.Value,
CustomerId = largestValue.o.OrganisationId
};
I'm not really sure about what you mean, but maybe you can try with this query.
select Id, max(Value)
from your_table
group by Id;
This gives you the max "Value column" value for each "Id column" value.
-- EDIT --
LINQ version:
var q = from t in dc.YourTable
group t by t.Id
into g
select new
{
Id = g.Id,
Value = (from t2 in g select t2.Value).Max()
};
Code not tested. I'm on the bus now... :-) Give it a try!

Join data from multiple tables into SelectList, and precede each dataset with a caption in MVC

So this is a bit more complex than what I've been trying to do in the past. Essentially I have a few different tables: employee.employees, companies.employees, dbo.all_employees, and companies. They are represented by the following models, in order: employees1, employees, all_employees, and companies.
all_employees has 3 columns all_id, employee_id, and employee_type. I'm attempting to make a SelectList to populate a drop drop list, that will house all of the employees divided by their appropriate company. I've managed to get all the employees by name into the combo box, but I can't seem to figure out how separate the employees.
So think of it like this. If all_employees has a record with an employee_type of 1, they belong to our company, and their first and last name should be pulled from employees1, if they have anything other than an employee_type of 1 then they belong to another company, and should be pulled from employees
Here is my rough code that currently pulls all the employees from both tables, unions them, and places them into a select list. I simply need to figure out how to easily split them up so it looks something like
-- Select Employee --
-- Company 1
First Last
First Last
-- Company 2
First Last
-- Company 3
First Last
Code
var query1 = from c in _db.employees1
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name };
var query2 = from c in _db.employees
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name };
var merged = query2.Union(query1);
ViewBag.employeeid = new SelectList(merged, "employee_id", "name");
I have come across a possible solution in the form of a third party extension. It implements optgroup, and allows me to to easily control everything. I think this is the best solution but I'm not entirely sure.
The library is here.
And my modified code now looks similar to this:
Controller:
var query1 = from c in _db.employees1
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name, companyID = 1, company = "LightHouse Electric" };
var query2 = from c in _db.employees
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name, companyID = c.company_id, company = "Other" };
var merged = query2.Union(query1);
var data = merged.ToList().Select(t => new GroupedSelectListItem {
GroupKey = t.companyID.ToString(),
GroupName = t.company,
Text = t.name,
Value = t.employee_id.ToString()
});
ViewBag.employeeid = data;
View:
#Html.DropDownGroupListFor(model => Model.employee_id, (IEnumerable<GroupedSelectListItem>)ViewBag.employeeid,
"-- Select --", new {#data_val = "true", #data_val_required = "The Name field is required.", #class="form-control"})

How to convert SQL Left Join query to Linq to Entity in C#?

I have a Table: Material(ID,Name,MAterialParentID)
SELECT c1.ID,c1.Name as ParentName,c2.id,c2.Name
FROM Material c1 Left JOIN Material c2
ON c1.ID = c2.MaterialParentID
ID ParentName id Name
1 Aluminium 2 Cavity
1 Aluminium 3 Copper
1 Aluminium 4 Flooring
2 Cavity NULL NULL
3 Copper NULL NULL
4 Flooring NULL NULL
5 Glass NULL NULL
I want to convert the above SQL Query to Linq Query using Liq to Entities.
Help Appreciated!
if the table is only for reading you could simply create a view and then when using reverse engineering make sure you have views imported.
or if you did want this done in LINQ here is the MSDN example
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
this is how yours would look
var Material = from M in db.Materials
join M2 in db.Materials on M.ID equals M2.MaterialParentID
select new {ParentID = M.ID, ParentName = M.Name, M2.ID, M2.Name };
i have edited my post above as you can see i have included the ParentID to make all columns unique
For this kind of problem linqpad is your friend.
I'd suggest something like:
var materials = (from m in context.Material
let moreMaterials = (from m2 in context.Material where m2.id == m.id select m2).FirstOrDefault()
select m).ToList();
But you can use linqpad to customise to your query requirements.

C# Linq finding value

I want to return the depart number that is not found Employee Table by comparing Department table.
Person Table
ID name salary job commision DeptID
--------------------------------------------------------------
P001 Jon 2000 Manager NULL 1
P002 Skeet 1000 Salesman 2000 1
P003 James 2340 Developer NULL 2
P004 greed 4500 Developer NULL 2
P005 Joel 1330 Salesman 1200 1
P006 Deol 5000 Architect NULL 2
Department Table
DeptID DeptName
1 Management
2 Software
3 ERP
SQL
select DeptId from dept
where deptId not in (select deptid from person)
When i try to execute the below code
LINQ
var qry = from n in context.Persons
where n.DeptID !=
(from m in context.Depts select m.DeptId)
select new { DeptID = n.DeptID };
I receive the following error
Operator '!=' cannot be applied to operands of type 'int?' and 'System.Linq.IQueryable'
var qry = from n in context.Persons
where n.DeptID !=
(from m in context.Depts select m.DeptId).FirstOrDefault()
select new { DeptID = n.DeptID };
You are trying to compare DeptID with a collection 1 or more department Ids. Even if there would only logically be one result for a DeptID, syntactically you need to specify that you want the first hit.
Suggested rephrasing:
var q = from m in context.Depts
where
!context.Persons.Select(p => p.DeptID).Contains(m.DeptID)
select new { DeptID = m.DeptID };
It sounds that your DeptID field in SQL is set to allow nulls. In that case you'd probably want something along the lines of this:
var qry = from n in context.Persons
where n.DeptID.Value !=
(from m in context.Depts select m.DeptId)
select new { DeptID = n.DeptID.Value };
I think it should be something like that. I tried to get a list of DeptID's first and then implement a NOT IN with contains :
var deptIDs = context.Persons
.Where( p => !context.Depts
.Select(d => new {DeptID = d.DeptID})
.Contains( p.DeptID )
)
.Select( p => new { DeptID = n.DeptID } );

Categories

Resources