Ok so I have been trying to figure out how to embed multiple select's
in a LINQ query and have been failing being that I don't use LINQ all that often.
I have come up with a fairly straight forward simple SQL statement I am trying to convert and I would appreciate it if anyone can help convert this to LINQ and explain the logic there.
SELECT * FROM TABLE_A
WHERE TABLE_B_REF IN
(SELECT TABLE_B_REF FROM TABLE_B
WHERE TABLE_B.TABLE_C_REF IN
(SELECT TABLE_C_REF FROM TABLE_C WHERE C_NUMBER = '10001'))
I have googled around but what I am getting is too complex to follow for multiple embedded
queries.
A SQL join seems much simpler here. Assuming you've set up navigation properties correctly, that would look a bit like this:
from a in db.TableA
where a.TableB.TableC.C_Number == "10001"
select a;
Or in fluent syntax:
db.TableA.Where(a => a.TableB.TableC.C_Number == "10001")
The corresponding SQL would be something like this:
SELECT a.*
FROM TABLE_A a
JOIN TABLE_B b ON a.TABLE_B_REF = b.TABLE_B_REF
JOIN TABLE_C c ON b.TABLE_C_REF = c.TABLE_C_REF
WHERE c.C_NUMBER = '10001'
Related
Hello i am totally new to Linq. I need to convert the following query to Linq and having a pretty hard time. Almost 3 hrs spent still unable to figure out. Most of the functions/methods in Sql like Distinct, Not in etc are missing in Linq. Even if they are available i am unable to figure out how to use them. Are there any alternative Methods/Functions in Linq with different names that i should be using or they don't even exist in Linq and i need to use a different approach ? I would be really helpful if someone could help me in converting the following query to Linq.
SQL Query
Select count(distinct(UserID)) from dbo.DeansStudents
inner join dbo.UserBarSession on DeansStudents.UserBarSessionID = UserBarSession.ID
inner join dbo.Users on users.ID = UserBarSession.UserID
where UserBarSessionID not in (
Select b.ID from dbo.DeansStudents,dbo.Users
left join dbo.Answers on answers.Student=users.ID
left join dbo.UserBarSession b on Answers.Student = b.UserID
where AnswerDate between b.StartDate and b.EndDate
and AnswerDate between 7/10/2011 and 3/12/2018
and UserBarSessionID = b.ID and DeanID= 12296 group by Answers.Student,users.FirstName,users.LastName,b.ID) and DeanID =12296
Query converted so far to LINQ
From my past couple of days into LINQ i managed to converted the first part of the Sql Query to LINQ. I am unable to continue with the second part. From "Select b.id........ "
var query = from deansStudent in dbo.DeansStudents
join userBarSession in dbo.UserBarSession
on deansStudent.UserBarSessionId equals userBarSession.Id
join users in dbo.Users
on userBarSession.UserId equals users.Id
//Need continuation from here
Most of the functions/methods in Sql like Distinct, Not in etc are missing in Linq
Distinct() is part of Linq, and NOT IN can be accomplished with the Except() Linq extension method.
With this answer, you should be able to finish your query.
I would like help to create this query in nhibernate using critera api (removed unnecessary parts from the sql):
SELECT this_.ID as ID120_1 FROM SS10_FOLDER this_
where this_.id in (select folderacce1_.resource_id from SS10_FOLDER_ACCESS folderacce1_ WHERE folderacce1_.GROUP_ID in (6174,6155));
My current solution uses "inner join" but I want to avoid it and use the "in select" as in the sql above. "groupIds" is a list of ids in c#.
var critiera = _session.CreateCriteria<H>();
criteria.CreateCriteria("Access", NHibernate.SqlCommand.JoinType.InnerJoin).Add(NHibernate.Criterion.Restrictions.In("Group.Id", groupIds));
Solved it like this:
DetachedCriteria subQuery = DetachedCriteria.For<A>("Access")
.Add(NHibernate.Criterion.Restrictions.In("Access.Group.Id", SmartContext.Current.GetGroupIds(Session).ToList())).SetProjection(Projections.Property("Access.Resource.Id"));
criteria.Add(Subqueries.PropertyIn("Id", subQuery));
I recently asked a question on StackOverflow (MySQL Returns All Rows When field = 0) regarding a query statement not working in MySQL. I now have a very similar problem, this time using OleDB where I am trying to use a join to include fields that have 0 as an entry, but not select every field in the table as a result.
The new look MySQL query posted in the above question as the accepted answer works without a hitch. However the OleDB counterpart I have written to do almost the same does not. It's a bit messy as the tables are not named very well (I didn't create this database) and I'm getting a simple syntax error;
myQuery.CommandText = "SELECT s.scm_num, s.scm_name, c.cr3_text, q.qsp_value, s.scm_bprefix, s.scm_nxbnum FROM qspreset q INNER JOIN sdccomp s LEFT OUTER JOIN cntref3 c ON s.scm_cntref3=c.cr3_id AND q.qsp_relat=s.scm_invtype AND q.qsp_what=13";
I'm querying another table here as well as the two involved in the LEFT OUTER JOIN and I believe that is where I am making the mistake.
Join conditions need to be with the join
myQuery.CommandText =
"SELECT s.scm_num, s.scm_name, c.cr3_text, q.qsp_value, s.scm_bprefix, s.scm_nxbnum
FROM qspreset q
INNER JOIN sdccomp s
on q.qsp_relat = s.scm_invtype AND q.qsp_what = 13
LEFT OUTER JOIN cntref3 c
ON s.scm_cntref3 = c.cr3_id";
q.qsp_what = 13 can be moved to a where
I happen to like this style
In the case of MSSQL T-SQL and some queries with a lot of joins I have gotten more efficient query plan by moving a where condition up into a join. The filter happened early rather that last.
If you don't believe you can put a hard value in a join see SQLfiddle
I'm running in to an issue that's baffling me. When I try to union two tables together, the query to the second table is generating an inner join back to the the first table. The whole point of using the union is to return a result if the record exists in either table, but this inner join is causing it to fail if a record is in the second table, but not the first.
I did some testing on a much smaller scale to see if I'm going crazy, and that doesn't seem to be the case.
I have two tables, OrderDetails and OrderDetailHistories. Back story: After a certain period of time records are removed from the details table and put into the histories table. The fields and everything are exactly the same. In fact, this is the entity for OrderDetailHistories:
public partial class OrderDetailsHistory : OrderDetail { }
So, to start out, I wrote a little test query that's a pretty good representation of what I'm seeing.
var test = this.context.OrderDetails
.Select(x => x.Descr)
.Union(this.context.OrderDetailsHistories
.Select(x => x.Descr))
.Where(x => x == "wat")
.ToList();
Which generates this query:
SELECT
[Distinct1].[C1] AS [C1]
FROM ( SELECT DISTINCT
[UnionAll1].[Descr] AS [C1]
FROM (SELECT
[Extent1].[Descr] AS [Descr]
FROM [dbo].[OrderDetails] AS [Extent1]
WHERE N'wat' = [Extent1].[Descr]
UNION ALL
SELECT
[Extent3].[Descr] AS [Descr]
FROM [dbo].[OrderDetails_History] AS [Extent2]
INNER JOIN [dbo].[OrderDetails] AS [Extent3] ON ([Extent2].[Order_No] = [Extent3].[Order_No])
WHERE N'wat' = [Extent3].[Descr]) AS [UnionAll1]
) AS [Distinct1]
Huh? Why does that second select statement even reference the details table? What happens when I use a concat? Same thing. Intersect? Same inner join. Okay, maybe instead of unioning first, then applying my condition, I can apply the conditions to each query, then just union the results.
How about this?
var query1 = this.context.OrderDetails.Where(x => x.Descr == "wat").Select(x => x.Descr);
var query2 = this.context.OrderDetailsHistories.Where(x => x.Descr == "wat").Select(x => x.Descr);
var result = query1.Concat(query2).ToList();
Generates almost the exact same query! Does anyone know what's going on here? Are my expectations just off?
If I throw a .ToList() at the end of the query1 and query2 statements above it works exactly like I'd expect, but then I lose my ability to do paging in sql and end up pulling down far too many records, when we're only displaying 10 per page.
Any help would be appreciated.
I don't know what EF approach you are using, I suppose Code first. But anyways, you are using it wrong or you don't know how it works. When you inherit your OrderDetailsHistory class from OrderDetail then it says, that OrderDetailsHistory is always an OrderDetail.
So if you want to select all orders you can just query OrderDetail and there will be also all OrderDetailsHistory entities:
this.context.OrderDetails
.Select(x => x.Descr)
.Where(x => x == "wat")
.ToList();
It is also important to know how data are stored in your DB. You are using table per class aproach - read some articles about it (e.g. http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt ) to understand how it works, then you will also understand why all your queries look "so strange"...
I want to know which one is better for performance:
//Logical
var query = from i in db.Item
from c in db.Category
where i.FK_IdCategory == c.IdCategory
Select new{i.name, c.name};
or
//Join
var query2 = from i in db.Item
join c in db.Category
on c.ID equals i.FK_IdCategory
Select new{i.name, c.name};
Performance of the two queries really depends on which LINQ provider and which RDBMS you're using. Assuming SQL Server, the first would generate the following query:
select i.name, c.name
from Item i, Category c
where i.FK_idCategory = c.IdCategory
Whereas the second would generate:
select i.name, c.name
from Item i
inner join Category c
on i.FK_idCategory = c.IdCategory
Which operate exactly the same in SQL Server as is explained in: Explicit vs implicit SQL joins
This depends on the ORM you're using and how intelligent it is at optimizing your queries for your backend.
Entity Framework can generate some pretty awful SQL if you don't do your linq perfectly, so I'd assume query2 is better.
The only way for you to know for sure would be to inspect the SQL being generated by the two queries.
Eyeballing it, it looks like query1 would result in both tables being pulled in their entirety and then being filtered against each other in your application, while query2 will for sure generate an INNER JOIN in the query, which will let SQL Server do what it does best - set logic.
Is that FK_IdCategory field a member of an actual foreign key index on that table? If not, make it so (and include the name column as an included column in the index) and your query will be very highly performant.
With linq2Sql or EntityFramework, you would probably do something like this:
var query = from i in db.Item
select new {i.name, i.Category.Name}
This will generate a proper SQL inner join.
I do assume that there is a foreign key relation between Item and Category defined.