I am calling SQL Server 10 from Entity Framework in C# and want to get a query hint into the request. The database has indexes which operated normally from SQL run in Management Studio, but when calling the command from C# using Entity Framework in Visual Studio, the query planner chooses a full scan when there is already an index.
I am creating dynamic predicates to request data in the following form:
data.attributeText = data.vegaDB.attributeText.AsExpandable().Where(parentPredicate.Compile()).ToList();
where parentPredicate is dynamically generated equivalent of:
(parentID = p1) AND (attributeName = 'name OR ... ')
From which the SQL Server query plan generates:
SELECT
[Extent1].[attributeID] AS [attributeID],
[Extent1].[parentID] AS [parentID],
[Extent1].[typeID] AS [typeID],
[Extent1].[attributeName] AS [attributeName],
[Extent1].[attributeData] AS [attributeData]
FROM [dbo].[attributeText] AS [Extent1]
So replacing the [Extent1] with the index [IX_parentID], which the direct sql call uses, by some extra command which does a query hint in the initial c# call would seem the solution. I have had a look around but no success yet. Any idea how to frame the question?
Do u think this is the right solution?
Run an SQL trace to find out what SQL query is actually being generated for this statement.
Does your predicate or an equivalent actually appear in the query as seen by SQL Server?
If it does appear, then you need to run that query through the Index Tuning wizard or similar.
If not, that's your problem - that would mean that Entity Framework is loading the entire table into memory and applying the predicate itself.
Updated I am pretty sure that this last is exactly what is happening: The AsExpandable() is failing to translate your predicate to SQL, so it is generating code to read the entire table, then applying the predicate to the returned data.
The solution is to stop using AsExpandable and use AsQueryable instead. The only reason to use AsExpandable is if AsQueryable doesn't offer the functionality you need, and I don't think that's the case here.
Try updating statistics for the related tables in your database, if statistics are outdated non-optimal query plans are likely to be used for all queries.
Related
I have some data in my database on the server. I have 2 options to get required data from server:
Entity Framework automatic generated queries
Using stored procedure in EF.
Which option is better?!
Suppose that required data is some determined rows of a table that has a routine query with a single input parameter. For example suppose this query:
SELECT *
FROM MyTable
WHERE someColumn = inputParameterValue
What's your suggestion? Writing a SP and call it via EF or writing a c# query so that EF automatically generates required query?!
Thanks for attention!
There are other considerations, not just performance. You might like to ask what fits in better with your coding style of standards.
A couple of things I'd do would be:
1) profile the sproc and the EF call use SQL/Persistance medium profiler.
2) maybe inspect the LINQ emitted by the LINQ to EF provider, using LinqPAD for example (or - its only just occured to me to look at the SQL when debugging your solution on the context call). And then make a judgement call.
I've inherited a C# / ASP.NET MVC / Entity Framework project with some slowness. There's not a lot of data in the DB but calls to .Include() were causing slowdowns.
However, I found something very strange. I have a 2k row table with just numbers (5 columns). I have indexes on the columns I'm searching.
When doing:
_entities.MyTable.Where(x=> x.Id1 == 4 && x.Id2 == 5).First()
it takes 1800ms on my development machine.
However, when I do :
_entities.MyTable.Where("it.Id1 = 4 and it.Id2 = 5").First()
it takes like 10ms.
What's the deal? I don't understand why the LINQ expression would be so slow.
Open Sql Profiler, look through the queries from EF. Try to analyze it, build plans. Seems that EF implenets queries in a strange way, without getting indexes.
Could it be that EF has to generate the SQL to do the where clause in the first example and in the second the SQL is much easier to generate as it can just plug in your already provided SQL?
Ive found that EF is very slow at generating queries, it seems unlikely in this case as its a rather simple query in both cases.
Have you tried compiling the first query and running it multiple times to check that the time to execute only includes actually running the SQL and not just generating it?
I normally use Entity Framework for my SQL queries which is great as it allows me to dynamically construct queries in a strongly-typed and maintainable fashion.
However, I'm on a project at the moment which utilises spatial queries. Most of my queries will output a resultset order by time or distance from a given co-ordinate. However, I have found that ordering by STDistance slows the query down 10 fold. (actually it slows down if I join on another table in addition to the "order by")
I have managed to optimize the query myself and got the performance back to where it should be, however, this query cannot be produced by Entity Framework.
So I could end up having a set of "order by time" queries generated by EF and then another set of "order by distance" queries as stored procedures in SQL Server. The trouble is that, basically, this latter set of queries would have to be created via string concatenation (either in an SP or C#).
I have been trying to get away from sql string concatenation for years now and these ORM frameworks are great for 99% of queries, however, I always find myself having to go back to string concanenation so I get the most optimal queries sent to the server. This is a maintenance nightmare though.
String concatenation was solved in ASP.NET with templating engines, which essentially allow you to build html strings. Does anyone know such a solution for SQL strings? Although it's a bit messy in some respects it would allow for the most optimal queries. In my view this would be better than
String concat in a stored proc
String concat in C#
Masses of duplicate code in stored procs covering all possible input parameters
LINQ queries which can create sub-optimal SQL
I'd love to know your thoughts about this general problem and what you think of my proposed solution.
thanks
Kris
Have you checked out the latest Entity Framework Beta? It is supposed to have support for spatial data types.
Also, if you want to build SQL queries dynamically, check out PetaPoco's SQL Builder. Some examples from the site:
Example 1:
var id=123;
var a=db.Query<article>(PetaPoco.Sql.Builder
.Append("SELECT * FROM articles")
.Append("WHERE article_id=#0", id)
.Append("AND date_created<#0", DateTime.UtcNow)
)
Example 2:
var id=123;
var sql=PetaPoco.Sql.Builder
.Append("SELECT * FROM articles")
.Append("WHERE article_id=#0", id);
if (start_date.HasValue)
sql.Append("AND date_created>=#0", start_date.Value);
if (end_date.HasValue)
sql.Append("AND date_created<=#0", end_date.Value);
var a=db.Query<article>(sql)
Example 3:
var sql=PetaPoco.Sql.Builder()
.Select("*")
.From("articles")
.Where("date_created < #0", DateTime.UtcNow)
.OrderBy("date_created DESC");
Maybe it would be an option to use a T4 template to generate the views (and corresponding queries). You could modify either the template or override the generated output selectively (although this may possibly also require you to modify the template).
Microsoft provides a T4 template for this purpose (assuming you're not using code-first, as I'm not sure the equivalent exists for that scenario).
Incidentally, pre-compiling the views also provides for faster startup as the views don't have to be generated at run-time.
Hard to understand the question.
Any kind of EF orm will always be slower than handcrafted sql. So we're left with manually creating and managing those sql queries. This can be done
manually write the procs
write "smart procs" with sql string concatenation in them
use templating engine for generating those procs at compile time
Write your own linq to sql provider for runtime generation of queries
all those have upsides and downsides, but if you have good unit test coverage it should protect you from obvious errors where someone has renamed the field in the database.
). I hope somebody wants some easy reputation by answering a simple question ::- ). How are you? Ok... joking ::- D.
The question is about how LINQ to Entities works with SQL Compact.
First of all, is there any way to profile stuff sent to an SQL Compact database? Apparently the Microsoft SQL Server Profiler does not work on SQL Compact databases... well... that's to be expected. But is there any other way to see the SQL query resulting from a LINQ select? Specifically:
IQueryable<some_table> query = from v in SomeEntity.some_table select v;
I am using some extension methods I found via Google to apply a "where" to the above select. Normally in Entity Framework you can't do that with LINQ (in .Net 3.5) but there are some workarounds.
What I want to do is verify if the workarounds get ALL the data from the table and then cheaply filter it, or if they are doing the RIGHT THING and only get the data that I asked for.
Secondly, do you know for sure that the statement below does NOT bring all the data in the table and puts it in memory after which does a cheap filter on it? (gosh I'd like a profiler to see what that dude is doing over there in the back-stage).
from v in SomeEntity.some_table where v.some_column == some_int_value select v;
I'll give you 2 answers: first, check out this link: How do I view the SQL generated by the Entity Framework?
Second, have a look at EF Prof.
i am using sql server 2005 and I think Linq generating queries for a different database version. I got the query string that linq was producing and pasted the linq directly in SQL Server Management studio and it failed with many errors. But the query works well if Linq is used. Any ideas what could be going on. If linq needs to know what database version to use how do I do that?
LINQ will create a parameterized query. You won't be able to directly copy the SQL into SSMS without adding definitions (and assigning values to) the parameters.