Linq to XML get item with id in id collection - c#

Given the XML below how would I go about getting a list of employees who have a position in the coordinators.coordinator > position_ids?
<employee id="000001">
<username>Bernard</username>
<first_name>BERNARD</first_name>
<last_name>FISHER</last_name>
<business_phone>011111111111</business_phone>
<cell_phone>011111111112</cell_phone>
<hr_contact_name>PETER MANNING</hr_contact_name>
<contract_description>Permanent</contract_description>
<positions>
<position id="00000002" isPrimary="1">
<title>DEVELOPMENT MANAGER</title>
<department id="DV001">DEVELOPMENT</department>
<manager_position>00000002</manager_position>
<coordinators>
<coordinator position_id="00013662"/>
<coordinator position_id="00014488"/>
<coordinator position_id="00022675"/>
<coordinator position_id="00024364"/>
</coordinators>
</position>
</positions>
</employee>
<employee id="000002">
<!-- ... --->
</employee>
Here is what I have so far:
//GET EMPLOYEE WITH CORORDINATORS AND SUBORINATES WITH POSITION ID
var q = from c in d.Elements().Elements().Elements("positions").Elements("position") where (string)(c.Attribute("id")) == "028782"
select new
{
PositionID = c.Parent.Parent.Attribute("id")
,Username = c.Parent.Parent.Element("username").Value
,FirstName = c.Parent.Parent.Element("first_name").Value
,LastName = c.Parent.Parent.Element("last_name").Value
,ContractDecription = c.Parent.Parent.Element("contract_description").Value
,Title = c.Element("title").Value
,Coordinators = (from coordinator
in d.Elements().Elements().Elements("positions").Elements("position")
join p in c on coordinator.Attribute("id").Value equals p.Attribute("id").Value
select new
{
PositionID = coordinator.Attribute("id")
,Username = coordinator.Parent.Parent.Element("username").Value
,FirstName = coordinator.Parent.Parent.Element("first_name").Value
,LastName = coordinator.Parent.Parent.Element("last_name").Value
,ContractDecription = coordinator.Parent.Parent.Element("contract_description").Value
,thenode = coordinator
})
,thenode = c
};
q.Dump();

You can try something like that:
var coordinatorIds =
d.Elements("employee")
.Elements("positions")
.Elements("coordinators")
.Elements("coordinator")
.Select(c => c.Attribute("position_id").Value)
.Distinct()
.ToArray();
var coordinators =
from c in d.Elements("employee")
join id in coordinatorIds on c.Attribute("id").Value equals id
select c;

Related

How to convert to Linq

How to convert the following query into linq
SELECT
a.ProductId,
a.Name,
a.Description,
b.Quoteid,
b.Productid,
b.Quantity,
b.OriginalPrice
FROM
Products AS a
LEFT JOIN
QuoteDtails AS b
ON a.ProductId = b.ProductId
AND b.QuoteId = 200;
Don't know where to add the AND condition.
Thanks and regards
You can try this linq if you want to write LEFT JOIN of linq, you need to add
into [temp collection] from [Left join talbe collection] in [temp collection].DefaultIfEmpty()
after Linq join
look like this.
from ss in Products
join aa in QuoteDtails
on ss.ProductId equals aa.ProductId into temp
from ds in temp.DefaultIfEmpty()
where ds.QuoteId = 200
select new
{
ProductId_P = ss.ProductId,
Name = ss.Name,
Description = ss.Description,
Quoteid = ds.Quoteid,
Productid_Q = ds.Productid,
Quantity = ds.Quantity,
OriginalPrice = ds.OriginalPrice
}
You can add AND condition in your LINQ query like this :
var res = from p in products
join q in quoteDtails on new { Criteria1 = p.ProductID, Criteria2 = 200 } equals new { Criteria1 = q.Productid, Criteria2 = q.Quoteid }
select new
{
ProductId_P = p.ProductID,
Name = p.Name,
Description = p.Description,
Quoteid = q.Quoteid,
Productid_Q = q.Productid,
Quantity = q.Quantity,
OriginalPrice = q.OriginalPrice
};

Linq left join and count - How To

I have the following Linq expression:
var employeeTypes = from t in DbContext.Set<SetupEmployeeType>().AsNoTracking()
join emp in DbContext.Set<Employee>().AsNoTracking() on t.EmployeeTypeId equals emp.EmployeeTypeId into employee
from subemp in employee.DefaultIfEmpty()
where t.MasterEntity == masterEntity
select new Model.SetupEmployeeTypeModel()
{
EmployeeTypeId = t.EmployeeTypeId,
Description = t.Description,
AllowProbation = t.AllowProbation,
IsActive = t.IsActive,
TotalEmployee = (subemp == null ? 0 : subemp.Count)
};
I need to set TotalEmployee property of my custom model.
So if there is no EmployeeTypeId associated to any Employee then TotalEmployee should be 0, else should be the Count of Employees.
Any clue how to do this?
If i may not wrong then consider using a subquery, like so -
var q = from empType in DbContext.Set<SetupEmployeeType>().AsNoTracking()
let empCount =
(
from emp in DbContext.Set<Employee>().AsNoTracking()
where empType.EmployeeTypeId == emp.EmployeeTypeId
select emp
).Count()
select new Model.SetupEmployeeTypeModel()
{
EmployeeTypeId = empType.EmployeeTypeId,
Description = empType.Description,
AllowProbation = empType.AllowProbation,
IsActive = empType.IsActive,
TotalEmployee = empCount
};
Using Group by.
var q = from empType in DbContext.Set<SetupEmployeeType>().AsNoTracking()
join empCnt in
(
from emp in DbContext.Set<Employee>().AsNoTracking()
group emp by emp.EmployeeTypeId into grp
select new { EmployeeTypeId = grp.Key, TotalEmp = grp.Count()}
) on empType.EmployeeTypeId equals empCnt.EmployeeTypeId into employees
from subemp in employees.DefaultIfEmpty()
where t.MasterEntity == masterEntity
select new Model.SetupEmployeeTypeModel()
{
EmployeeTypeId = empType.EmployeeTypeId,
Description = empType.Description,
AllowProbation = empType.AllowProbation,
IsActive = empType.IsActive,
TotalEmployee = subemp.TotalEmp
};
I came up with the following solution:
var employeeTypes = from t in DbContext.Set<SetupEmployeeType>().AsNoTracking()
join empg in
(
from emp in DbContext.Set<Employee>().AsNoTracking()
group emp by emp.EmployeeTypeId into g
select new { EmployeeTypeId = g.Key, Total = g.Count() }
) on t.EmployeeTypeId equals empg.EmployeeTypeId into employee
from subemp in employee.DefaultIfEmpty()
where t.MasterEntity == masterEntity
select new Model.SetupEmployeeTypeModel()
{
EmployeeTypeId = t.EmployeeTypeId,
Description = t.Description,
AllowProbation = t.AllowProbation,
IsActive = t.IsActive,
TotalEmployee = subemp.Total
};

C# LINQ: Get count for each row

Here the query for retrieving all the comptes in my base.
I would like to add a number within the object GridCompte in order to count the element inside the list (1,2,3...):
var comptes = (from c in Comptes
join s in Societies on c.IdSoc equals s.IdSoc
select new GridCompte
{
SocCompteId = c.IdCompte,
Name = c.Name,
Nb = ??? COUNT ???,
.....
SocName = s.Name
}).ToList();
I tried using the group statement, but i didn't manage to achieve my goal.
Any suggestions?
First prepare your linq only for the fields you want to get
var comptes = from c in Comptes
join s in Societies on c.IdSoc equals s.IdSoc
select new
{
SocCompteId = c.IdCompte,
Name = c.Name,
.....
SocName = s.Name
};
Now use index option that is available in Select
var finalComptes = (comptes.AsEnumerable()
.Select((comptes, index) => new GridCompte()
{
SocCompteId = c.IdCompte,
Name = c.Name,
Nb = index + 1,
.....
SocName = s.Name
}).ToList();

One to Many Linq to XML query

I have an XML string that looks like this:
<Attributes>
<ProductAttribute id="1">
<ProductAttributeValue>
<Value>a</Value>
</ProductAttributeValue>
</ProductAttribute>
<ProductAttribute id="2">
<ProductAttributeValue>
<Value>a</Value>
</ProductAttributeValue>
<ProductAttributeValue>
<Value>b</Value>
</ProductAttributeValue>
</ProductAttribute>
</Attributes>
I would like to return an IEnumerable like this:
Id Value
1 a
2 a b
I have tried this and only got the "b" value for Id "2":
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
from pav in pa.Elements("ProductAttributeValue").Elements("Value")
select new
{
Id = (int)pa.Attribute("id"),
Value = (string)pav
};
I tried this:
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = pa.Elements("ProductAttributeValue").Elements("Value")
};
But could not cast Value as a string. Using LINQPad the output was like this:
Id Value
1 a
2 <Value>a</Value>
<Value>b</Value>
I am trying to just return the values. Is this even possible?
Thanks.
If you wanted a contatenated string of those values like "a b"
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = string.Join(" " ,
pa.Elements("ProductAttributeValue")
.Elements("Value")
.Select(x=>x.Value)
.ToArray())
};
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = from pav in pa.Elements("ProductAttributeValue").Elements("Value") select pav.Value
};
Of course, Value will be an IEnumerable<string>.
Edit:
If you want the output to concat the Value elements into one string you can do this:
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = string.Join(" ", (from pav in pa.Elements("ProductAttributeValue").Elements("Value")
select pav.Value).ToArray())
};
Then the output will be:
Id Value
1 a
2 a b

How to generate SQL COUNT(*) OVER (PARTITION BY {ColumnName}) in LINQ-to-SQL?

Is it possible to generate the following SQL query by using LINQ-to-SQL query expression or method chains which is defer-executable?
Data Structure
alt text http://www.freeimagehosting.net/uploads/e062a48837.jpg
Select Distinct ClassRoomTitle,
Count(*) Over(Partition By ClassRoomNo) As [No Sessions Per Room],
TeacherName,
Count(*) Over(Partition By ClassRoomNo, TeacherName) As [No Sessions Per Teacher] From ClassRoom
Expected Result
alt text http://www.freeimagehosting.net/uploads/47a79fea8b.jpg
Try this:
var vGroup = from p in ClassRoom
group p by new { p.ClassRoomNo, p.TeacherName }
into g
from i in g
select new
{
i.ClassRoomNo,
i.TeacherName,
i.ClassRoomTitle,
NoSessionsPerTeacher = g.Count()
};
var pGroup = from p in vGroup
group p by new { p.ClassRoomNo }
into g
from i in g
select new
{
i.ClassRoomTitle,
NoSessionsPerRoom = g.Count(),
i.TeacherName,
i.NoSessionsPerTeacher
};
var result = pGroup.OrderBy(p => p.ClassRoomNo).ThenBy(p => p.TeacherName);
I didn't test the above but you can check my original code in case I got something wrong in the rewrite:
var vGroup = from p in Products
group p by new { p.ProductId, p.VariantId }
into g
from i in g
select new
{
i.ProductId,
i.VariantId,
VariantCount = g.Count()
};
var pGroup = from p in vGroup
group p by new { p.ProductId }
into g
from i in g
select new
{
i.ProductId,
ProductCount = g.Count(),
i.VariantId,
i.VariantCount
};
var result = pGroup.OrderBy(p => p.ProductId).ThenBy(p => p.VariantId);
var classRooms = from c in context.ClassRooms
group c by new {c.ClassRoomNo} into room
select new {
Title = room.First().ClassRoomTitle,
NoSessions = room.Count(),
Teachers = from cr in room
group cr by new {cr.TeacherName} into t
select new {
Teacher = t.Key,
NoSessions = t.Count()
}
};
A bit more structured than the posted expected result, but I find that to be better.
You can always use SelectMany if you want to go back to unstructured:
var unstructured = classRooms
.SelectMany(c=> c.Teachers.Select( t=> new {
Title = c.Title,
SessionsPerRoom = c.NoSessions,
Teacher = t.Teacher,
SessionsPerTeacher = t.NoSessions
});

Categories

Resources