Slow running EF query - sql

I have this query and it is running VERY slowly. Why would this be? I have added all the non NVARCHAR(max) columns into a non-clustered index but still have this problem.
return (from ir in IndemnityRatings
where date >= ir.ValidFrom &&
date <= ir.ValidTo &&
ir.CoverLevel.CoverLevelId == coverLevelId &&
ir.Age == age &&
ir.OwnIndemnity == ownIndemnity &&
ir.CustomerIndemnity == customerIndemnity &&
ir.FullTimePartTimeReference == fullOrPartTime &&
ir.TurnoverReference == turnover
select ir).SingleOrDefault();
Incidently, when executing the same query (the equivalent thereof) directly on the database I get results back immediately. Furthermore I get a single row when calling the database dirctly (which is correct) and null when calling this piece of code.

Related

Different performance from SQL Server query from Management Studio vs EF Core 5

I wrote a simple EF Core query that makes a select on a table using some where clause to filter data: start date and finish date between the actual date and a field (DescrizioneCommessa) containing a value.
var query = _ctx.Commessas
.Where(x => (x.DataInizioCommessa.HasValue && x.DataInizioCommessa <= DateTime.Now) || !x.DataInizioCommessa.HasValue)
.Where(x => (x.DataFineCommessa.HasValue && x.DataFineCommessa >= DateTime.Now) || !x.DataFineCommessa.HasValue)
.Where(x => x.DescrizioneCommessa.Contains(pattern))
.OrderBy(x => x.DescrizioneCommessa);
To get the raw SQL I just execute the statement:
var sql = facis.ToQueryString();
And the resultant query is:
DECLARE #__pattern_0 nvarchar(50) = N'COMUNE';
SELECT *
FROM [Commessa] AS [c]
WHERE (([c].[DataInizioCommessa] IS NOT NULL AND [c].[DataInizioCommessa] <= GETDATE()) OR [c].[DataInizioCommessa] IS NULL)
AND (([c].[DataFineCommessa] IS NOT NULL AND ([c].[DataFineCommessa] >= GETDATE())) OR [c].[DataFineCommessa] IS NULL)
AND ((#__pattern_0 LIKE N'') OR (CHARINDEX(#__pattern_0, [c].[DescrizioneCommessa]) > 0))
ORDER BY [c].[DescrizioneCommessa]
I notice that it takes very long to perform the query comparing to its hand-written version:
SELECT *
FROM Commessa
WHERE (DescrizioneCommessa LIKE '%COMUNE%')
AND (DataInizioCommessa <= GETDATE() OR DataInizioCommessa IS NULL)
AND (DataFineCommessa >= GETDATE() OR DataFineCommessa IS NULL);
EF Query takes even more than one minute to elaborate, while the normal one is immediate.
I verified that the problem is this part of where clause:
AND ((#__pattern_0 LIKE N'') OR (CHARINDEX(#__pattern_0, [c].[DescrizioneCommessa]) > 0))
If I substitute the above line with:
AND (DescrizioneCommessa LIKE '%COMUNE%')
the problem is resolved, the performance is optimal.
Why this line
.Where(x => x.DescrizioneCommessa.Contains(pattern))
creates this issue?
This is documented behaviour in EF.Core as discussed on SO: Entity framework EF.Functions.Like vs string.Contains
As a general proposition, LIKE expressions do NOT work well with query optimisers. In larger datasets this becomes a serious problem, even though they work just fine in much smaller unoptimized sets. The optimisation is heavily dependent on the pattern being matched and if it is a ranged lookup or not. In your case the pattern cannot make use indexes, EF is simply trying to convert it into an expression that might be indexable, in which case after running the expression enough the rest of the database insights engines would advise you to implement an appropriate index.
Read about some other discussions about parsing String.Contains() to SQL in git hub: https://github.com/dotnet/efcore/issues/474
When you explicitly want to use SQL LIKE, EF Core added EF.Functions.Like():
Like(DbFunctions, String, String)
Like-operator in Entity Framework Core 2.0
var query = _ctx.Commessas
.Where(x => (x.DataInizioCommessa.HasValue && x.DataInizioCommessa <= DateTime.Now) || !x.DataInizioCommessa.HasValue)
.Where(x => (x.DataFineCommessa.HasValue && x.DataFineCommessa >= DateTime.Now) || !x.DataFineCommessa.HasValue)
.Where(x => EF.Functions.Like(x.DescrizioneCommessa, pattern)
.OrderBy(x => x.DescrizioneCommessa);

Linq query output does not match with Sql query output

Repository.Calls
.Count(call => call.OutcomeActionDate.Value >= fourWeeksStartDate &&
call.OutcomeActionDate.Value < threeWeeksStartDate &&
call.UserId == user.UserId);
Above query gives me output 1 and the sql query:
select *
from calls
where userid = 1006 and
outcomeactiondate >= '2013-08-19' and
OutcomeActionDate < '2013-08-26'
gives me the output 15.
The output 15 is correct. I am not sure why is the linq query giving me incorrect value ?
All the parameter values used in select query are same as passed in the linq query.
Try to use Date part of filtered dates:
Calls.Count(call => call.OutcomeActionDate.Value >= fourWeeksStartDate.Date &&
call.OutcomeActionDate.Value < threeWeeksStartDate.Date &&
call.UserId == user.UserId);

How to change variable value on demand in JasperReports

I am working with iReport. Here is the situation:
I have some parameters named branchID, spType.
I have created one variable named branchName (string) which is by default null.
What I need to do is, to change/ edit the value of the variable branchName depending on the values of branchID and spType
How can I do this with JasperReports using If Else. Is it something with the properties of the variable branchName? Any help/ Suggestion would be highly appreciated.
Expressions Scripting Language in Jasper reports is your friend!
What i can fathom from your query is that you want to compute the value of a variable based on values of two parameters. In short, you want to do something like:-
Simple if-else
If (branchId == 1 && spType == "abc")
branchName = "Xyz1";
else
branchName = "Xyz2";
In Jasper scripting language, the above expression can be written as :-
($P{branchId}==1 &&
$P{spType} != null &&
$P{spType}.equals("abc"))?"Xyz1":"Xyz2"
Nested If-else
If (branchId == 1 && spType == "abc")
branchName = "Xyz1";
else if (branchId = 2 && spType == "def")
branchName = "Xyz2";
else
branchName = "Xyz3";
Jasper expression:
( $P{branchId} ==1 &&
$P{spType} !=null &&
$P{spType}.equals("abc") ) ? "Xyz1" :
(($P{branchId} == 2 &&
$P{spType} != null &&
$P{spType}.equals("def")) ? "Xyz2" : "Xyz3");
For more details, have a look at this tutorial:
http://www.tutorialspoint.com/jasper_reports/jasper_report_expression.htm
Here is a similar stackoverflow question also:
doing comparison if else in JasperReports
For core concept, Page no. 10 of this pdf:
http://jasperreports.sourceforge.net/JasperReports-Ultimate-Guide-3.pdf
iReport support scripting using expressions.
You can right click on a report element and click edit expression to open the expression editor.
Some useful notes in this answer as well.

Performance issue with SQL server due to sql query

Need some help to solve this error:
The query processor ran out of internal resources and could not
produce a query plan. This is a rare event and only expected for
extremely complex queries or queries that reference a very large
number of tables or partitions. Please simplify the query. If you
believe you have received this message in error, contact Customer
Support Services for more information.
SQL query: (I am just putting one of the query. I got 9 such queries running)
var query1 = from article in _db.Articles
from scl in article.Scls
where article.publishDate < DateTime.Now
&& article.removalDate > DateTime.Now
&& article.finished == true
&& article.flagged== true
&& listOfScl.Contains(scl.id)
select article;
var query2 = from article in _db.Articles
from com in article.Coms
where article.publishDate < DateTime.Now
&& article.removalDate > DateTime.Now
&& article.finished == true
&& article.flagged== true
&& listOfCom.Contains(com.id)
select article;
query = (query1.Union(query2)).Distinct();
Don't know what is wrong with query its working fine but giving some performance issue on SQL Server.
I need some help to avoid such error and re-write this SQL query without using UNION.
Thanks in advance.
Also note that by default LINQ does UNION, which will eliminate duplicates, therefore there is no need for Distinct, which will likely improve performance.
"re-write this SQL query without using UNION.". How is this?
var query1 = from article in _db.Articles
from scl in article.Scls
where article.publishDate < DateTime.Now
&& article.removalDate > DateTime.Now
&& article.finished == true
&& article.flagged== true
&& (
listOfScl.Contains(scl.id)
|| listOfCom.Contains(com.id)
)
select article;
You could try the performance of this, so that you don't need a distinct. It will involve a subquery though, so it's hard to say what will perform better without testing:
var query1 = _db.Articles.Where(article => article.publishDate < DateTime.Now
&& article.removalDate > DateTime.Now
&& article.finished == true
&& article.flagged== true
&& ( article.Scls.Any(s=> listOfScl.Contains(s.id))
|| article.Coms.Any(c=> listOfCom.Contains(c.id))
)
);

LINQ to SQL: subfilter in where conditions

This question may have been answered somewhere (and if so I would love to have the link!). But since I don't know what type of linq query I'm trying to do, I haven't been able to find anything to help me.
I already have a very simple query setup to get all records of type DomainSequences.
var query = db.DomainSequences;
There are different types of domain sequences. I want to get all of them. However, for records that have a DomainType attribute equal to 'AT', then I only want to return some of those of 'AT' records (ie. do a where clause on those to filter the 'AT' records but still want to return all non 'AT' records.
More simply put, I want to get all DomainSequence records, but for the records that have a DomainType == "AT", then return those only if they meet certain conditions.
I can think of a way of doing it by doing something like:
query.Where(x => x.DomainType != "AT" || (x.DomainType == "AT" && AT conditions....));
I think this should work but the problem comes when I have to do subfilters on other columns and then it starts to get messier and complicated very quickly.
Ideally, I would like to do something like
query.Where(x => x.DomainType == "AT" || x.DomainType == "KS")
.WhereIf(y => y.DomainType == "AT" then apply filter on those)
.WhereIf(z => z.DomainType == "KS" then apply filter to these);
I'm not sure if there is a way to do this type of subfilter in LINQ or in SQL (though I imagine there is). Any suggestions on how this could be done relatively cleanly?
Thanks!
It's really not all that different than what you might write in SQL. In fact, if you would try the query expression syntax approach, you might find that particular connection easier to make.
var query = from domain in db.DomainSequences
where (domain.DomainType == "AT" && domain.Foo == 42 && ...)
|| (domain.DomainType == "KS" && domain.Foo = 117 && ...)
select domain;
That maps nicely to the SQL you might expect to write
SELECT *
FROM DomainSequences
WHERE
(DomainType = 'AT' AND Foo = 42 AND ...)
OR
(DomainType = 'KS' AND Foo = 117 AND ...)
You could, of course, keep it in the fluent extension method syntax using lambdas, of course, it's just a single .Where(...) invocation, after all.
query.Where(x => x.DomainType == "AT" || x.DomainType == "KS")
.Where(y => y.DomainType != "AT" || other filter)
.Where(z => z.DomainType != "KS" || other filter);