SELECT
SI_2.[StudGUID] ,SI_2.[ClassName],
SI_2.[StudGUID],SI_1.[StuName],SI_1.[Title],SI_1.[StuMobileNumber]
FROM
[StudentInfo2] AS SI_2
INNER JOIN
[StudentInfo] AS SI_1 ON SI_2.[StudGUID]=SI_1.[StuCode]
WHERE
SI_2.[ClassID] IN (SELECT SC.[ClassID]
FROM [SchoolClass] AS SC
LEFT JOIN [BookClass] AS BC ON SC.[ClassID]=BC.[ClassID]
WHERE BC.[ClassID] IS NULL AND SchoolYear = 2015)
AND SI_2.[isMonitor] = 1
Question: I want use Linq to implement the code in SQL. How to use Linq to implement the code?
Seek help!
Related
can anybody help me to convert this SQL query to LINQ code in MVC? I need to return a list. The DB context entity is: _dbContext.
select distinct table1.AIG_ID, table1.GMT_NAME, table1.AIG_Number
from table1 left join table2 on table1.AIG_ID = table2.AIG_ID**
var data=(from item in db.table1 join
item1 in db.table2 on item.AIG_ID equals item1.AIG_ID
select new {item.AIG_ID ,item.GMT_NAME ,item.AIG_Number }).GroupBy(a=>a.AIG_ID).select(a=>a.FirstOrDefault()).ToList();
I write this part for your distinct in sql
GroupBy(a=>a.AIG_ID).select(a=>a.FirstOrDefault())
I'm trying to rewrite SQL procedure to Linq, it all went well and works fine, as long as it works on small data set. I couldn't really find answer to this anywhere. Thing is, I have 3 joins in the query, 2 are left joins and 1 is inner join, they all join to each other/like a tree. Below you can see SQL procedure:
SELECT ...
FROM sprawa s (NOLOCK)
LEFT JOIN strona st (NOLOCK) on s.ident = st.id_sprawy
INNER JOIN stan_szczegoly ss (NOLOCK) on s.kod_stanu = ss.kod_stanu
LEFT JOIN broni b (NOLOCK) on b.id_strony = st.ident
What I'd like to ask you is a way to translate this to Linq. For now I have this:
var queryOne = from s in db.sprawa
join st in db.strona on s.ident equals st.id_sprawy into tmp1
from st2 in tmp1.DefaultIfEmpty()
join ss in db.stan_szczegoly on s.kod_stanu equals ss.kod_stanu
join b in db.broni on st2.ident equals b.id_strony into tmp2
from b2 in tmp2.DefaultIfEmpty()
select new { };
Seems alright, but when checked with SQL Profiler, query that is sent to database looks like that:
SELECT ... FROM [dbo].[sprawa] AS [Extent1]
LEFT OUTER JOIN [dbo].[strona] AS [Extent2]
ON [Extent1].[ident] = [Extent2].[id_sprawy]
INNER JOIN [dbo].[stan_szczegoly] AS [Extent3]
ON [Extent1].[kod_stanu] = [Extent3].[kod_stanu]
INNER JOIN [dbo].[broni] AS [Extent4]
ON ([Extent2].[ident] = [Extent4].[id_strony]) OR
(([Extent2].[ident] IS NULL) AND ([Extent4].[id_strony] IS NULL))
As you can see both SQL queries are bit different. Effect is the same, but latter works incomparably slower (less than a second to over 30 minutes). There's also a union made, but it shouldn't be the problem. If asked for I'll paste code for it.
I'd be grateful for any advice on how to better the performance of my Linq statement or how to write it in a way that is translated properly.
I guess I found the solution:
var queryOne = from s in db.sprawa
join st in db.strona on s.ident equals st.id_sprawy into tmp1
where tmp1.Any()
from st2 in tmp1.DefaultIfEmpty()
join ss in db.stan_szczegoly on s.kod_stanu equals ss.kod_stanu
join b in db.broni on st2.ident equals b.id_strony into tmp2
where tmp2.Any()
from b2 in tmp2.DefaultIfEmpty()
select new { };
In other words where table.Any() after each into table statement. It doesn't make translation any better but has sped up execution time from nearly 30minutes(!) to about 5 seconds.
This has to be used carefully though, because it MAY lead to losing some records in result set.
Does anyone know if there is a tool to convert T-SQL code to LINQ?
I'm struggling to find a way of converting the following SQL code to LINQ:
select * from actions as a
inner join
(
select max(actionid) as maxactionid, threaduid from actions as a
where a.actiontypeid not in (3,4)
group by threaduid
) as a2 on a2.maxactionid = a.actionid
where a.userid <> 2
Any help appreciated!
check out: http://www.sqltolinq.com/
There is linqer from http://www.sqltolinq.com/.
Linqer is a SQL to LINQ converter tool. It helps you to learn LINQ and convert your existing SQL statements.
Im trying to convert a SQL join to LINQ. I need some help in getting the nested join working in LINQ.
This is my SQL query, Ive cut it short just to show the nested join in SQL:
select distinct
txtTaskStatus as TaskStatusDescription,
txtempfirstname+ ' ' + txtemplastname as RaisedByEmployeeName,
txtTaskPriorityDescription as TaskPriorityDescription,
dtmtaskcreated as itemDateTime,
dbo.tblTask.lngtaskid as TaskID,
dbo.tblTask.dtmtaskcreated as CreatedDateTime,
convert(varchar(512), dbo.tblTask.txttaskdescription) as ProblemStatement,
dbo.tblTask.lngtaskmessageid,
dbo.tblMessage.lngmessageid as MessageID,
case when isnull(dbo.tblMessage.txtmessagesubject,'') <> '' then txtmessagesubject else left(txtmessagedescription,50) end as MessageSubject,
dbo.tblMessage.txtmessagedescription as MessageDescription,
case when dbo.tblMessage.dtmmessagecreated is not null then dbo.tblMessage.dtmmessagecreated else CAST(FLOOR(CAST(dtmtaskcreated AS DECIMAL(12, 5))) AS DATETIME) end as MessageCreatedDateTime
FROM
dbo.tblAction RIGHT OUTER JOIN dbo.tblTask ON dbo.tblAction.lngactiontaskid = dbo.tblTask.lngtaskid
LEFT OUTER JOIN dbo.tblMessage ON dbo.tblTask.lngtaskmessageid = dbo.tblMessage.lngmessageid
LEFT OUTER JOIN dbo.tblTaskCommentRecipient
RIGHT OUTER JOIN dbo.tblTaskComment ON dbo.tblTaskCommentRecipient.lngTaskCommentID = dbo.tblTaskComment.lngTaskCommentID
ON dbo.tblTask.lngtaskid = dbo.tblTaskComment.lngTaskCommentTaskId
A more seasoned SQL programmer wouldn't join that way. They'd use strictly left joins for clarity (as there is a strictly left joining solution available).
I've unraveled these joins to produce a hierarchy:
Task
Action
Message
TaskComment
TaskCommentRecipient
With associations created in the linq to sql designer, you can reach these levels of the hierarchy:
//note: these aren't outer joins
from t in db.Tasks
let actions = t.Actions
let message = t.Messages
let comments = t.TaskComments
from c in comments
let recipients = c.TaskCommentRecipients
DefaultIfEmpty produces a default element when the collection is empty. Since these are database rows, a default element is a null row. That is the behavior of left join.
query =
(
from t in db.Tasks
from a in t.Actions.DefaultIfEmpty()
from m in t.Messages.DefaultIfEmpty()
from c in t.Comments.DefaultIfEmpty()
from r in c.Recipients.DefaultIfEmpty()
select new Result()
{
TaskStatus = ???
...
}
).Distinct();
Aside: calling Distinct after a bunch of joins is a crutch. #1 See if you can do without it. #2 If not, see if you can eliminate any bad data that causes you to have to call it. #3 If not, call Distinct in a smaller scope than the whole query.
Hope this helps.
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM [Orders] AS [t0]
LEFT OUTER JOIN ([Order Details] AS [t1]
INNER JOIN [Products] AS [t2] ON [t1].[ProductID] = [t2].[ProductID]) ON [t0].[OrderID] = [t1].[OrderID]
can be write as
from o in Orders
join od in (
from od in OrderDetails join p in Products on od.ProductID equals p.ProductID select od)
on o.OrderID equals od.OrderID into ood from od in ood.DefaultIfEmpty()
select o
I want to achieve the following in Linq to Entities:
Get all Enquires that have no Application or the Application has a status != 4 (Completed)
select e.*
from Enquiry enq
left outer join Application app
on enq.enquiryid = app.enquiryid
where app.Status <> 4 or app.enquiryid is null
Has anyone done this before without using DefaultIfEmpty(), which is not supported by Linq to Entities?
I'm trying to add a filter to an IQueryable query like this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where e.Applications.DefaultIfEmpty()
.Where(app=>app.Status != 4).Count() >= 1
select e);
Thanks
Mark
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Do this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where (!e.Applications.Any())
|| e.Applications.Any(app => app.Status != 4)
select e);
I don't find LINQ's handling of the problem of what would be an "outer join" in SQL "goofy" at all. The key to understanding it is to think in terms of an object graph with nullable properties rather than a tabular result set.
Any() maps to EXISTS in SQL, so it's far more efficient than Count() in some cases.
Thanks guys for your help. I went for this option in the end but your solutions have helped broaden my knowledge.
IQueryable<Enquiry> query = Context.EnquirySet;
query = query.Except(from e in query
from a in e.Applications
where a.Status == 4
select e);
Because of Linq's goofy (read non-standard) way of handling outers, you have to use DefaultIfEmpty().
What you'll do is run your Linq-To-Entities query into two IEnumerables, then LEFT Join them using DefaultIfEmpty(). It may look something like:
IQueryable enq = Enquiry.Select();
IQueryable app = Application.Select();
var x = from e in enq
join a in app on e.enquiryid equals a.enquiryid
into ae
where e.Status != 4
from appEnq in ae.DefaultIfEmpty()
select e.*;
Just because you can't do it with Linq-To-Entities doesn't mean you can't do it with raw Linq.
(Note: before anyone downvotes me ... yes, I know there are more elegant ways to do this. I'm just trying to make it understandable. It's the concept that's important, right?)
Another thing to consider, if you directly reference any properties in your where clause from a left-joined group (using the into syntax) without checking for null, Entity Framework will still convert your LEFT JOIN into an INNER JOIN.
To avoid this, filter on the "from x in leftJoinedExtent" part of your query like so:
var y = from parent in thing
join child in subthing on parent.ID equals child.ParentID into childTemp
from childLJ in childTemp.Where(c => c.Visible == true).DefaultIfEmpty()
where parent.ID == 123
select new {
ParentID = parent.ID,
ChildID = childLJ.ID
};
ChildID in the anonymous type will be a nullable type and the query this generates will be a LEFT JOIN.