Using sql with index in linq query - c#

I'm using a dbcontext linq query:
var list = context.MyTable.Where(x => x.IsValid).ToList();
The SqlProfiler shows this Sql Query:
SELECT * FROM [MyTable] WHERE IsValid = 1
The problem is that in this table I'm using a lot of sql indexes, and by default it uses the wrong index and query is taking a very long time. I need to add the index I have in the table into the query.
In other words how to get this query from linq?
SELECT * FROM [MyTable] WITH(INDEX(PK_MyIndexName)) WHERE IsValid = 1

Related

Linq Sql Query result is different from the SQL query run in the database

When I run the query in C# code using Linq the result returned is different from the sql query run in sql server
SQL query
SELECT TOP (1000) [Teamid]
,[TeamName]
,[TemplateId]
,[TemplateName]
FROM [MPFT_SendIT].[dbo].[VMTemplate]
where
Teamid=1
Result
SQL Query of the VMTemplate View
SELECT dbo.Team.Id AS Teamid, dbo.Team.TeamName,
dbo.MessageTemplate.Id AS TemplateId,
dbo.MessageTemplate.TemplateName
FROM dbo.Team INNER JOIN
dbo.TemplateLookup ON dbo.Team.Id =
dbo.TemplateLookup.TeamId INNER JOIN
dbo.MessageTemplate ON dbo.TemplateLookup.TemplateId =
dbo.MessageTemplate.Id
where
TeamId= 1
Result
Linq SQL
var teamid = _db.TeamLookups.Where(i => i.UserId == 20).Select(x =>
x.TeamId).ToList(); // teamid return value is 1
ViewBag.messageTemplate = _db.VMTemplates.Where(i =>
teamid.Contains(i.Teamid));
Linq query only returns one record line 1 of the sql query instead of 2 records as expected. Any help on how to solve this issue ?
Why Contains()? You should use equality operator rather
_db.VMTemplates.Where(i => teamid == i.Teamid).ToList();
Per your comment, then your Linq expression should work just fine. Add a ToList() to it
ViewBag.messageTemplate = _db.VMTemplates.Where(i =>
teamid.Contains(i.Teamid)).ToList();

How to Write this SQL with linq to sql

Let's say I have a list with 2 or more customerIds and a list with two or more order dates. I want an SQL query like this from linq to sql
SELECT *
FROM Orders
WHERE (CustomerId = #CustomerId1
AND (OrderDate = #OrderDate1 OR OrderDate = #OrderDate2))
OR
(CustomerId = #CustomerId2
AND (OrderDate = #OrderDate1 OR OrderDate = #OrderDate2))
The list with CustomerIds and order dates is not fixed, so I need to loop through it when building the query.
I found a solution for this by using PredicateBuilder
from http://www.albahari.com/nutshell/predicatebuilder.aspx

GroupBy query is slow what are the other options?

I need a query to select rows with minimum Insert Date Time. but groupby query is very slow
what can I do instead of groupby?
How can improve the performance of the query?
Is there any other way to write this query using linq?
Number of rows in my table is around 600,000 rows and growing
fullsimnumber isn't indexed but isdeleted and insertdatetime are indexed.
fullsimnumber is a column which consist of three indexed coloumn prec+cod+subscribec.
my problem is with linq queries which always gives timeout exception.
I changed fullsimnumber to groupby prec,cod,subscribec which are indexed but still getting tiemout exception
Im using linq to EF, (code first style) and my query in sql is:
SELECT *
FROM dbo.Sim AS t1
JOIN (SELECT FullSimNumber,MIN(InsertDateTime) AS insd
FROM dbo.Sim
GROUP BY FullSimNumber) AS t2
ON t1.FullSimNumber = t2.FullSimNumber AND t1.InsertDateTime = t2.insd
WHERE t1.IsDeleted = 0
and my query in linq
from s in ADbContext.Numbers
where !s.IsDeleted
group s by s.FullSimNumber
into g
let sd = g.OrderBy(x => x.InsertDateTime).FirstOrDefault()
select sd;
without any data on indexes and amounts of rows and such it is hard to know what exactly is needed to make your query faster. One thing which is worthwhile to try out is this:
SELECT *
FROM dbo.Sim AS t1
CROSS APPLY (
SELECT TOP 1 FullSimNumber
, InsertDateTime AS insd
FROM dbo.Sim t2
WHERE t1.FullSimNumber = t2.FullSimNumber
AND t1.InsertDateTime = t2.insd
ORDER BY InsertDateTime DESC
) AS t2
WHERE t1.IsDeleted = 0
Again this could very well be worse! test it and compare the execution times and load.

Getting distinct rows in LINQ

I need to get the distinct row values from a table using LINQ. The query i used is
var results = (from statename in dsobject.dbo_statetable select statename).Distinct();
It is giving all the rows of the table named "dbo_statetable" but i need only the distinct statename. What should be the query to achieve this?
Its sql equivalent is select distinct statename from dbo_statetable
You need to specify the property:
var results = (from x in dsobject.dbo_statetable select x.Statename).Distinct();
// ^^^^^^^^^^
The variable after from does not specify the column. It is like a table alias in SQL. Your LINQ statement is roughly equivalent to this SQL:
SELECT DISTINCT * FROM dbo_statetable AS statename
dsobject.dbo_statetable.Select(s => s.statename).Distinct()

'Invalid column name [ColumnName]' on a nested linq query

Last update
After alot of testing, I realised that if i ran the same query over the same dataset (in this case a Northwind) table on SQL 2000 and SQL 2005, I get two different results.
On SQL 2000, i get the error that's in the question.
On SQL 2005, it succeeds.
So I've concluded that the query generated by linqpad doesn't work on sql 2000. To reproduce this, run:
OrderDetails
.GroupBy(x=>x.ProductID)
.Select(x=>new {product_id = x.Key, max_quantity = x.OrderByDescending(y=>y.UnitPrice).FirstOrDefault().Quantity}).Dump();
on a Northwind DB in sql 2000. The sql translation is:
SELECT [t1].[ProductID] AS [product_id], (
SELECT [t3].[Quantity]
FROM (
SELECT TOP 1 [t2].[Quantity]
FROM [OrderDetails] AS [t2]
WHERE [t1].[ProductID] = [t2].[ProductID]
ORDER BY [t2].[UnitPrice] DESC
) AS [t3]
) AS [max_quantity]
FROM (
SELECT [t0].[ProductID]
FROM [OrderDetails] AS [t0]
GROUP BY [t0].[ProductID]
) AS [t1]
Original Question
I've got the following query:
ATable
.GroupBy(x=> new {FieldA = x.FieldAID, FieldB = x.FieldBID, FieldC = x.FieldCID})
.Select(x=>new {FieldA = x.Key.FieldA, ..., last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault().Timestamp})
results in:
SqlException: Invalid column name 'FieldAID' x 5
SqlException: Invalid column name 'FieldBID' x 5
SqlException: Invalid column name 'FieldCID' x 1
I've worked out it has to do with the last query to Timestamp because this works:
ATable
.GroupBy(x=> new {FieldA = x.FieldAID, FieldB = x.FieldBID, FieldC = x.FieldCID})
.Select(x=>new {FieldA = x.Key.FieldA, ..., last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault()})
The query has been simplified. The purpose is to group by a set of variables and then show the last time this grouping occured in the db.
I'm using Linqpad 4 to generate these results so the Timestamp gives me a string whereas FirstOrDefault gives me the whole object which isn't ideal.
Update
On further testing I've noticed that the number and type of SQLException is related to the class created in the groupby clause.
So,
ATable
.GroupBy(x=> new {FieldA = x.FieldAID})
.Select(x=>new {FieldA = x.Key.FieldA, last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault()})
results in
SqlException: Invalid column name 'FieldAID' x 5
You should use the SQL profiler to check if the SQL generated against the 2 databases is different.
We have only had two problems where something ran on SQL Server 2005 but not on SQL Server 2000. In both cases it was due to the lack of support for Multiple Active Result Sets (MARS) in SQL Server 2000. In one case it led to locking in the database, in the other case it led to a reduction of performance.

Categories