How is this Nested Set SQL query converted into a LINQ query? - c#

Querying a Nested Set Model table, here's the SQL... how can this be written in LINQ?
SELECT parent.name
FROM nested_category AS node, nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.name = 'FLASH'
ORDER BY parent.lft;
particularly, the FROM part... never tried to do anything like that in LINQ.

Perhaps something like:
var query = from node in nested_category
from parentNode in nested_category
where node.lft >= parentNode.lft && node.rgt <= parentNode.rgt
&& node.name == "FLASH"
orderby parent.left
select parent.name;

if you do the LEFT OUTER join like that (that is without using into and DefaultIfEmpty()) then the top-level parent node will not be output (because it's parent is NULL)
My SQL version which goes:
SELECT
B.ELEMENT_CODE ParentElement,
A.ELEMENT_CODE ChildElement
FROM NESTED_SET_STRUCTURE AS A
LEFT OUTER JOIN NESTED_SET_STRUCTURE AS B
ON B.PROCEDURE = 'TEST1' AND B.FROM_LEFT = (SELECT MAX(C.FROM_LEFT)
FROM NESTED_SET_STRUCTURE AS C
WHERE C.PROCEDURE = 'TEST1' AND A.FROM_LEFT > C.FROM_LEFT
AND A.FROM_LEFT < C.TO_RIGHT)
WHERE
A.PROCEDURE = 'TEST1';
Translates as:
var nestedSets1 =
from a in NESTED_SET_STRUCTUREs
join b in NESTED_SET_STRUCTUREs on
new { a.PROCEDURE, FROM_LEFT = ((from c in NESTED_SET_STRUCTUREs
where c.PROCEDURE.Equals("TEST1")
&& a.FROM_LEFT > c.FROM_LEFT
&& a.FROM_LEFT < c.TO_RIGHT
select (c.FROM_LEFT)).Max()) } equals
new { b.PROCEDURE, b.FROM_LEFT } into bo
from bb in bo.DefaultIfEmpty()
where
a.PROCEDURE.Equals("TEST1")
orderby a.FROM_LEFT
select new {
ParentElement = bb.ELEMENT_CODE,
ChildElement = a.ELEMENT_CODE
};
Hope that helps, Paul.

Related

Converting an SQL Containing inner and Outer Joins into Linq

I need to convert an SQL query to Linq/Lambda expression, I am trying doing the same but not getting the desired results.
SQL:
SELECT b.*, n.notes
FROM Goal_Allocation_Branch as b
INNER JOIN Goal_Allocation_Product as g
on b.Product = g.ProductID
and b.Year = g.Year
left join Goal_Allocation_Branch_Notes as n
on b.branchnumber = n.branch
and n.year = ddlYear
WHERE b.Year = ddlYear
and g.Show = 1
and branchnumber = ddlBranch
I am new to Linq , I am getting error on Join Clause , and X is not containing any data from first Join
var result = (from br in _DB_Branches.Goal_Allocation_Branches
join pr in _DB_Product.Goal_Allocation_Products on new { br.Product, br.Year } equals new {Product= pr.ProductID, Year= pr.Year }
join n in _DB_Notes.Goal_Allocation_Branch_Notes.Where(n => n.Year == ddlYear) on br.BranchNumber equals n.Branch into Notes
from x in Notes.DefaultIfEmpty()
select new BranchNotesViewModel
{
Year = x.Year,
BranchNumber = x.Branch,
ProductID = x.ProdID
}
).ToList();
Update: My First Join clause initially giving error "The type of one of the expression in Join Clause is incorrect " is resolved, when I Changed On Clause
from
"on new { br.Product, br.Year } equals new {pr.ProductID, pr.Year}"
"on new { br.Product, br.Year } equals new {Product=pr.ProductID,Year= pr.Year}"
still not getting desired results as expected from above SQL query. Please advise..
It should be something like this (see note):
var result =
(from br in _DB_Branches.Goal_Allocation_Branches
join pr in _DB_Product.Goal_Allocation_Products
on br.Product equals pr.ProductID
from n in _DB_Notes.Goal_Allocation_Branch_Notes.Where(x=>
x.branch == br.branchnumber
&& x.year == ddlYear
).DefaultIfEmpty()
where
br.Year == ddlYear
&& and br.Year == pr.Year
&& pr.Show == 1
&& br.branchnumber == ddlBranch
select new BranchNotesViewModel
{
Year = ...,
BranchNumber = ...,
ProductID = ...
}
).ToList();
Note: Change the select, to the properties you want.
Edit: fixed some syntax errors.
I finally figured out the correct answer. Working absolutely fine
var result = (from br in _DB_Branches.Goal_Allocation_Branches
join pr in _DB_Product.Goal_Allocation_Products on new { br.Product, br.Year } equals new { Product = pr.ProductID, Year = pr.Year }
join n in _DB_Notes.Goal_Allocation_Branch_Notes.Where(n=>n.Year==ddlYear) on br.BranchNumber equals n.Branch into Notes
where br.Year==ddlYear
&& pr.Show== true
&& br.BranchNumber==ddlBranch
from x in Notes.DefaultIfEmpty()
select new BranchNotesViewModel
{
Year=x.Year,
BranchNumber=x.Branch,
ProductID=br.Product,
Notes = x.Notes,
//All other fields needed
}
).ToList();

How to optimize linq query?

I have difficulty in getting an average score of students in each department.
while every department there are many faculties, each faculty there are many courses, each course there are many students, and every student has a lot of value.
the query that I have made, I get quite a lot of the time constraints that are required to display the same data capture.
please help to optimize the query that I made this.
double TotalNilaiMutu = 0;
double JumSKS = 0;
double ipkMhs = 0;
double totalIPK = 0;
var queryDepartemen = (from so in StrukturOrganisasis
join dp in Departemens on so.ID equals dp.ID
orderby dp.ID
select new{dp.ID, so.Inisial, so.Nama}).ToList();
foreach(var departemen in queryDepartemen){
var queryMayor = (from my in Mayors
where my.DepartemenID == departemen.ID && my.StrataID == 2
select my.ID).ToList();
var queryMhs = (from ms in MahasiswaSarjanas
where queryMayor.Contains(ms.MayorID) &&
(
from sm in StatusMahasiswas
where
(
from ts in TahunSemesters
where ts.TahunAwal == 2013
select ts.ID
)
.Contains(sm.TahunSemesterID)
select sm.NIM
)
.Contains(ms.NIM)
select ms.NIM).ToList();
ipkMhs = 0;
foreach(var nim in queryMhs){
var queryNilai = (from kr in KRS
join hm in HurufMutus on kr.HurufMutuID equals hm.ID
join kur in
(
from ku in Kurikulums
join mk in MataKuliahs on ku.MataKuliahID equals mk.ID
select new {ku.ID, mk.Nama, mk.SKS}
)
on kr.KurikulumID equals kur.ID
where kr.NIM==nim
select new {
nilai = hm.NilaiMutu * kur.SKS,
sks = kur.SKS
});
TotalNilaiMutu = 0;
JumSKS = 0;
foreach(var ipk in queryNilai){
TotalNilaiMutu += ipk.nilai;
JumSKS += ipk.sks;
}
if(double.IsNaN(TotalNilaiMutu/JumSKS)) ipkMhs+=0;
else ipkMhs += TotalNilaiMutu/JumSKS;
}
if(double.IsNaN(ipkMhs/queryMhs.Count())) totalIPK=0;
else totalIPK=ipkMhs/queryMhs.Count();
Console.WriteLine(departemen.Nama +" -> "+ totalIPK +" : "+ ipkMhs +" / "+queryMhs.Count());
}
Have you tried adding AsParallel()?
var queryDepartemen = (from so in StrukturOrganisasis.AsParallel()
join dp in Departemens on so.ID equals dp.ID
orderby dp.ID
select new{dp.ID, so.Inisial, so.Nama}).ToList();
foreach(var departemen in queryDepartemen.AsParallel()){
var queryMayor = (from my in Mayors
where my.DepartemenID == departemen.ID && my.StrataID == 2
select my.ID).ToList();
var queryMhs = (from ms in MahasiswaSarjanas.AsParallel()
where queryMayor.Contains(ms.MayorID) &&
(
from sm in StatusMahasiswas
where
(
from ts in TahunSemesters
where ts.TahunAwal == 2013
select ts.ID
)
.Contains(sm.TahunSemesterID)
select sm.NIM
)
.Contains(ms.NIM)
select ms.NIM).ToList();

What's the better way to write this linq query?

SQL:
SELECT node.CategoryId,
node.CategoryName,
node.Description,
node.Lft, node.Rgt,
node.ShowOnMenu,
(COUNT(parent.CategoryName) - 1) AS Level,
(CASE WHEN node.Lft = node.Rgt - 1 THEN 'TRUE' ELSE 'FALSE' END) AS Leaf
FROM Article_Category AS node,
Article_Category AS parent
WHERE node.Lft BETWEEN parent.Lft AND parent.Rgt
GROUP BY node.CategoryId,node.CategoryName,node.Description,node.Lft,node.Rgt,node.ShowOnMenu
ORDER BY node.Lft
My linq expression:
var list = (from node in DbContext.Categories
from parent in DbContext.Categories
where node.Lft >= parent.Lft && node.Lft <= parent.Rgt
select new
{
node.CategoryId,
node.CategoryName,
node.Description,
node.Lft,
node.Rgt,
node.ShowOnMenu,
ParentName = parent.CategoryName,
} into x
group x by new
{
x.CategoryId,
x.CategoryName,
x.Description,
x.Lft,
x.Rgt,
x.ShowOnMenu,
} into g
orderby g.Key.Lft
select new
{
CategoryId = g.Key.CategoryId,
CategoryName = g.Key.CategoryName,
Description = g.Key.Description,
Lft = g.Key.Lft,
Rgt = g.Key.Rgt,
ShowOnMenu = g.Key.ShowOnMenu,
Level = g.Count() - 1,
IsLeaf = g.Key.Lft == g.Key.Rgt - 1
}).ToList();
My question:
The linq expression is too long, there is two 'select new' expressions, i wonder how to make it shorter?
What's the corresponding Extension Method to the linq query? How can i express the "from... from...where..." with Extension method?
The first select new .. into x I don't see why you need, try removing it and write group node by new...
"from...from" is written as a lambda expression like this:
Categories.SelectMany(n => Categories, (n, p) => new { Node = n, Parent = p });

LINQ query with sub where clause

I have a SQL query :
SELECT [Paypoint]
,[Department]
,[EmployeeCode]
,[Gender]
,[EmployeeTitle]
,[Initials]
,[Surname]
,[ItemsIssuedDate]
,[ItemsIssuedStockNumber]
FROM [MyTable] AS a
WHERE
(
[ItemsIssuedDate] = ( SELECT max([ItemsIssuedDate])
FROM [MyTable] AS b
WHERE a.[Paypoint] = b.[Paypoint]
AND a.[Department] = b.[Department]
AND a.[EmployeeCode] = b.[EmployeeCode]
AND a.[Gender] = b.[Gender]
AND a.[Surname] = b.[Surname]
)
How would one get the comparitive LINQ query ? I cannot use the SQL query as the Data is already in a DataSet, and now needs to be modified further...
I have attempted, but this does not work :
var query = from a in excelTable
where
(
from c in excelTable
group c by new
{
c.Paypoint,
c.EmployeeCode
} into g
where string.Compare(a.Paypoint, g.Key.Paypoint) == 0 && string.Compare(a.EmployeeCode, g.Key.Paypoint) == 0
select g.Key.Paypoint
)
select a;
var query = from a in MyTable
group a by new {
a.Paypoint,
a.Department,
a.EmployeeCode,
a.Gender,
a.Surname
} into g
select g.OrderByDescending(x => x.ItemsIssuedDate)
//.Select(x => new { required properties })
.First();
You can also select anonymous object with required fields only. Up to you.
Your most direct with the SQL query will be:
var query =
from a in excelTable
let maxIssueDate =
(from b in excelTable
where a.Paypoint == b.Paypoint &&
a.Department == b.Department &&
a.EmployeeCode == b.EmployeeCode &&
a.Gender == b.Gender &&
a.Surname == b.Surname
select b.ItemsIssueDate).Max()
where a.ItemsIssueDate == maxIssueDate
select a;

LINQ to SQL in and not in

What is in and not in equals in LINQ to SQL?
For example
select * from table in ( ...)
and
select * from table not in (..)
What is equal to the above statement in LINQ to SQL?
You use, where <list>.Contains( <item> )
var myProducts = from p in db.Products
where productList.Contains(p.ProductID)
select p;
Or you can have a list predefined as such:
int[] ids = {1, 2, 3};
var query = from item in context.items
where ids.Contains( item.id )
select item;
For the 'NOT' case, just add the '!' operator before the 'Contains' statement.
I'm confused by your question. in and not in operate on fields in the query, yet you're not specifying a field in your example query. So it should be something like:
select * from table where fieldname in ('val1', 'val2')
or
select * from table where fieldname not in (1, 2)
The equivalent of those queries in LINQ to SQL would be something like this:
List<string> validValues = new List<string>() { "val1", "val2"};
var qry = from item in dataContext.TableName
where validValues.Contains(item.FieldName)
select item;
and this:
List<int> validValues = new List<int>() { 1, 2};
var qry = from item in dataContext.TableName
where !validValues.Contains(item.FieldName)
select item;
Please Try This For SQL Not IN
var v = from cs in context.Sal_Customer
join sag in context.Sal_SalesAgreement
on cs.CustomerCode equals sag.CustomerCode
where
!(
from cus in context.Sal_Customer
join
cfc in context.Sal_CollectionFromCustomers
on cus.CustomerCode equals cfc.CustomerCode
where cus.UnitCode == locationCode &&
cus.Status == Helper.Active &&
cfc.CollectionType == Helper.CollectionTypeDRF
select cus.CustomerCode
).Contains(cs.CustomerCode) &&
cs.UnitCode == locationCode &&
cs.Status == customerStatus &&
SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate) < 36
select new CustomerDisasterRecoveryDetails
{
CustomerCode = cs.CustomerCode,
CustomerName = cs.CustomerName,
AgreementDate = sag.AgreementDate,
AgreementDuration = SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate)
};
Please Try This For SQL IN
context.Sal_PackageOrItemCapacity.Where(c => c.ProjectCode == projectCode && c.Status == Helper.Active && c.CapacityFor.Contains(isForItemOrPackage)).ToList();

Categories

Resources