I have below sql query which I want to convert into LINQ to obtain exactly same results and returned by below query
select *
from (
select distinct DocID
from UserViewDoc
where UserViewDoc.UVID in (102558)) a
left outer join
(
select distinct UserViewDoc.DocID
from UserViewDoc
inner join UserViewHeader on UserViewDoc.UVID = UserViewHeader.UVID
where UserViewDoc.UVID not in (102558)
and UserViewHeader.IsLock = 1) b on a.DocID = b.DocID
where b.DocID is null
)
What I have tried so far is below LINQ statement
var v = (from uvd in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewDoc>()
where IDs.Contains(uvd.UVID)
select new { uvd.DocID, uvd.UVID });
var c = ((from uvd in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewDoc>()
join uvh in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewHeader>() on uvd.UVID equals uvh.UVID
where !IDs.Contains(uvh.UVID) && uvh.IsLock == true
select new { uvd.DocID, uvd.UVID } ));
var d = (from id in v
join ids in c on id.UVID equals ids.UVID into vc
from sub in vc.DefaultIfEmpty()
where sub == null
select id);
The problem I am facing is running the SQL query is returning 30583 records and LINQ version of it is returning all of the 30613 records
I rewrote the query to be exactly like the sql query, i believe that this is the way:
var firstQuery = (from u in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewDoc>()
where IDs.Contains(u.UVID)
select u.DocID).Distinct();
var innerQuery = (from u in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewDoc>()
join uvh in this.ViewSelectorControl.LDReviewContext.GetTable<UserViewHeader>() on uvh.UVID equals u.UVID
where IDs.Contains(u.UIVD) == false
&& uvh.IsLock
select u.DocID).Distinct();
var resultQuery = from f in firstQuery
join i in innerQuery on i equals f into lout
from i in lout.DefaultIfEmpty()
where i == null
select f;
Related
I am trying to convert a SQL Command to Linq but gets the error 'Unable to process the type 'Anonymous type', because it has no known mapping to the value layer.'
SQL Code
SELECT ooe.id, parts.title, appro.totalAppro, allo.TotalAllotment, cost.total_cost, (CASE WHEN cost.total_cost IS NULL THEN (SELECT allo.TotalAllotment) ELSE (SELECT allo.TotalAllotment - cost.total_cost) END) AS unobligated
FROM pmTA_OoeGeneral AS ooe INNER JOIN
pmTA_Particulars AS parts ON ooe.particular_id = parts.id LEFT OUTER JOIN
pmTA_vwObligationRequestDetailsTotalCostByOoe AS cost ON ooe.id = cost.ooe_general_id
LEFT OUTER JOIN pmTA_vwTotalAllotmentGeneralFund AS allo ON ooe.id = allo.ooe_general_id
LEFT OUTER JOIN pmTA_vwTotalAppropriationGeneralFund AS appro ON ooe.id = appro.ooe_general_id
WHERE (ooe.year = #year) AND (ooe.project_category_id = #cat) and (ooe.type = #type) order by ooe.id
LINQ Code
var gvStatusGenOffices = (from a in db.iBudget_OoeGeneral
join b in db.iBudget_Particulars on a.ParticularID equals b.id
join c in obligationRequestDetailsTotalCostByOoe on a.id equals c.id
join d in totalAllotmentGeneralFund on a.id equals d.id
join e in totalAppropriationGeneralFund on a.id equals e.id
where a.YearID==year && a.ProjectID==cat && a.type==type
orderby a.id
select new
{
id = a.id,
title = b.title,
appro = e.totalAppro,
allo = d.totalAllo,
cost = c.totalCost,
unobligated = c.totalCost==null ? d.totalAllo : d.totalAllo - c.totalCost
}).ToList();
db.iBudget_OoeGeneral and db.iBudget_Particulars are model class in my project
obligationRequestDetailsTotalCostByOoe , totalAllotmentGeneralFund and totalAppropriationGeneralFund are variables with list values.
The question is what is causing this error? I tried looking the web for some answers but none was showing up.
UPDATE
var obligationRequestDetailsTotalCostByOoe = (from p in db.iBudget_ObligationRequestDetails
where p.ooe_general_id != null && p.is_approved == 1
group p by p.ooe_general_id into g
select g)
.AsEnumerable()
.Select(g => new {
id = g.Key,
totalCost = g.Sum(p => Convert.ToDouble(p.amount))
}).ToList();
Originally, obligationRequestDetailsTotalCostByOoe , totalAllotmentGeneralFund and totalAppropriationGeneralFund were Views in SQL Server. Since I was practicing how to code Linq, I didn't create a View and just made a var with list same with the original View Code in SQL.
I am trying to translate the following query with self join to a LINQ expression.
select r2.* from depends d
join request r on d.DESC =r.DESC
join request r2 on d.ID=r2.ID
and d.TYPE ='sometype'
where r.ID= 12345
How can I correct the following LINQ query to match the correct SQL query above?
var result = (from d in depends
join r in request on d.DESC equals r.DESC
join r2 in request on d.ID == r2.ID && d.TYPE == incomingType.ToString()
where r.ID == incomingId
select r2).AsEnumerable();
Why don't you simple use a Where clause if your incomingType is fixed?
Also there is syntax for multiple join conditions, as shown here: LINQ Joining in C# with multiple conditions
E.g.:
var result = (from d in depends
where d.TYPE == incomingType.ToString()
join r in request on
new { ID = r.ID, desc = r.DESC }
equals
new { ID = d.ID, desc = d.DESC }
where r.ID == incomingId
select r).AsEnumerable();
If your incomingType is not actually fixed, and it gets its value from the depends table, you can just add a third parameter to the join condition, e.g.
var result = (from d in depends
where d.TYPE == incomingType.ToString()
join r in request on
new { ID = r.ID, desc = r.DESC, type = r.someType1 }
equals
new { ID = d.ID, desc = d.DESC, type = d.someType2 }
where r.ID == incomingId
select r).AsEnumerable();
I have the following SQL Query:
SELECT DISTINCT *
FROM Documents d
LEFT JOIN
Invoices
ON (i.invoicedocumentid = d.id or i.jobsheetdocumentid = d.id)
INNER JOIN
PurchaseOrders PO ON i.poid = PO.id
LEFT JOIN
HelpDeskFaults f
ON f.id = PO.helpDeskFaultId
LEFT JOIN stores s
ON s.id = f.storeid
WHERE s.name = 'Linden Drive'
OR d.id in (
SELECT u.id as 'docid'
FROM documents u
INNER JOIN stores s
ON u.storeid = s.id
WHERE s.name = 'Linden Drive'
)
ORDER BY d.Id
So far my linq query looks like this:
var documents = from doc in context.Documents
from invoice in context.Invoices
join po in context.PurchaseOrders on invoice.PurchaseOrder.PurchaseOrderId equals po.PurchaseOrderId
join hdf in context.HelpDeskFaults on po.HelpdeskFaultId equals hdf.ID into hdfpo
from hs in hdfpo.DefaultIfEmpty()
join store in context.Stores on hs.StoreID equals store.ID into hsstore
from hss in hsstore.DefaultIfEmpty()
where hss.Name.Contains(jobSearchParams.StoreName) && (invoice.InvoiceDocumentId == doc.ID || invoice.JobSheetInvoiceId == doc.ID)
select doc;
But the sql that is produced is nothing like what I expected.
Can anyone give me any pointers of how to improve my linq query.
This is what I would translate your SQL query into
var results =
(from doc in context.Documents
from invoice in (
from inv in context.Invoices
where inv.InvoiceDocumentId == doc.ID || inv.JobSheetInvoiceId == doc.ID
select inv).DefaultIfEmpty()
from hs in invoice.PurchaseOrder.HelpDeskFaults.DefaultIfEmpty()
from hss in hs.Stores.DefaultIfEmpty()
where hss.Name == "Linden Drive" || doc.Store.Name == "Linden Drive"
order by doc.ID
select new
{
Document = doc,
Invoice = invoice,
invoice.PurchaseOrder,
HelpDeskFault = hs,
Store = hss,
}).Distinct();
I included that anonymous class of the 5 entities because your SQL is using Select *. I would recommend changing it to only return the minimum required set of fields.
When I run this Query in SQL I get what I want:
SELECT Auckland_Park.Formative.[Formative Name]
FROM Auckland_Park.LearningUnit
INNER JOIN Auckland_Park.Formative
ON Auckland_Park.LearningUnit.ID = Auckland_Park.Formative.FK_LU
INNER JOIN Auckland_Park.Reference
INNER JOIN Auckland_Park.Course
ON Auckland_Park.Reference.FK_Course = Auckland_Park.Course.ID
ON Auckland_Park.LearningUnit.ID = Auckland_Park.Reference.FK_LU
WHERE Auckland_Park.Course.Name = 'BI'
My result:
Querying SQL Build
Report Develop
Java App Develop
Andriod App Set up
SharePoint Server
But when I work with my C# app I'm using LINQ to SQL, my LINQ Query looks like this:
//LINQ Query to fill Foramtive Name ComboBox
CTUDataContext data = new CTUDataContext();
var course = (from r in data.LearningUnits
join a in data.Formatives
on r.ID equals a.FK_LU
join f in data.References
on r.ID equals f.FK_LU
join g in data.Courses
on f.FK_LU equals g.ID
where g.Name == ("BI")
select new
{
formativeName = a.Formative_Name,
ID = a.ID
}
).ToList();
txtFormativeName.ItemsSource = course;
txtFormativeName.DisplayMemberPath = "formativeName";
txtFormativeName.SelectedValuePath = "ID";
It seems the same, but I'm not getting the same result that I'm getting with the SQL Query above.
//LINQ Query to fill Foramtive Name ComboBox
CTUDataContext data = new CTUDataContext();
var course = (from r in data.LearningUnits
join a in data.Formatives
on r.ID equals a.FK_LU
join f in data.References
on r.ID equals f.FK_LU
join g in data.Courses
on f.FK_LU equals g.ID
where g.Name == ("BI")
select new
{
formativeName = a.Formative_Name,
ID = a.ID
}
).ToList();
txtFormativeName.ItemsSource = course;
txtFormativeName.DisplayMemberPath = "formativeName";
txtFormativeName.SelectedValuePath = "ID";
ANSWER:
on f.FK_LU equals g.ID
f.FK_LU
must be replaced with
f.FK_Course
my sql statement is
SELECT c.type,c.title,c.datereg, d.ranknum
FROM T_News AS c
INNER JOIN (
SELECT a.id, COUNT(*) AS ranknum
FROM T_News AS a
INNER JOIN T_News AS b
ON (a.type = b.type)
AND (a.datereg >= b.datereg)
GROUP BY a.id
HAVING COUNT(*) <= 3
) AS d ON (c.id = d.id)
ORDER BY c.type, d.ranknum
that i get http://rickosborne.org/blog/2008/01/sql-getting-top-n-rows-for-a-grouped-query/
for Getting TOP N rows for a grouped query
EFUnitOfWork EF = new EFUnitOfWork();
T_NewsRepository News = new T_NewsRepository();
News.UnitOfWork = EF;
var query =
from news1 in News.All()
join news2 in News.All()
on news1.type equals news2.type into resjoin
group news1 by news1.id into idgroup
where idgroup.Count() <= 3
select new { idgroup };
var x = query.ToList();
I did not get any error , but "where idgroup.Count() <= 3" did not work and i get all rows in db as result
Break it down into it's smallest components and then compose the larger query from that. Let's start with the innermost query that makes sense:
SELECT
a.id, COUNT(*) AS ranknum
FROM
T_News AS a
INNER JOIN T_News AS b ON
(a.type = b.type) AND
(a.datereg >= b.datereg)
GROUP BY
a.id
HAVING
COUNT(*) <= 3
I'd convert this to:
// Items with counts/ranknum
var ranknum =
from a in News.All()
join b in News.All() on
a.type equals b.type
where
a.datereg > b.datereg
group by a.id into g
select new { g.Key as id, g.Count() as ranknum };
// Filter the ranknum.
ranknum = ranknum.Where(rn => rn.ranknum <= 3);
Then joining that with the outer query:
SELECT
c.type,c.title,c.datereg, d.ranknum
FROM
T_News AS c
INNER JOIN (<sub-query from above>) as d ON
c.id = d.id
ORDER BY
c.type, d.ranknum
That part becomes simple, as it's just a join between two existing queries.
var query =
from c in News.All()
join rn in ranknum on c.id = rn.id
orderby c.type, rn.ranknum
select new { c.type, c.title, c.datereg, rn.ranknum };
Chances are the SQL that LINQ-to-Entities generates for this is going to look really ugly, and probably be inefficient, in which case, you might want to consider placing this logic in a stored procedure and then calling that through LINQ-to-Entities (which is generally true for more complex queries).