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.
Related
I personally like SQL, but I realize I probably need to follow the EF design. At times and with other team members, SQL will be used. When a Raw SQL Query is made, does it return objects/properties for my C# code? If I have five tables mapped, and I do a raw query, are corresponding properties returned?
The answer is yes. You need to define your entity class for the result of your raw SQL Query, remember to make the name of the properties exactly the same with the name of returned columns in your query.
context.Database.SqlQuery<YourEntity>("your query").ToList();
With EF, you have to create and maintain the POCO for your raw query, and your query text will probably languish inside double quotes somewhere. Why not grab QueryFirst? Your sql will be in .sql file, and the wrapper code, including POCO will be generated and managed for you. And there are numerous other advantages!
You don't have to use one approach exclusively. Lots of folk use EF, then Dapper or something like it when they need/want to "revert" to SQL. QueryFirst isn't an ORM and doesn't replace EF. Obviously if you let EF manage your schema, (code first, model first) then non-EF queries risk being walloped by EF schema changes. But with QueryFirst at least, you can "recompile" your queries to assure they're working and still return what you need after EF has changed your schema.
Disclaimer: I wrote QueryFirst.
I have imported a SQL Server stored procedure into the .edmx file. I'm calling the generated method like:
entity.MySP(stringInput)
Does the stringInput parameter need to be validated (for SQL injections etc) when using EF, or can I assume EF does that for me? If not, is there a method I can call to escape/validate the input parameter?
I'm using SQL Server 2008 R2, .NET 4.0, C#, ASP.NET MVC 4, VS2010.
EDIT:
Note that I'd like to use LINQ instead of calling a SP, but I'm using FREETEXT, so I think this is the more elegant solution.
You can read more about LINQ to Entity Framework Security here, http://msdn.microsoft.com/en-us/library/cc716760.aspx. Look at the section titled "Security Considerations for Queries".
To answer your question specifically, Entity Framework will call your stored procedure and pass in the stringInput value. That means even if stringInput is a SQL statement meant to inject something harmful into your database, just passing it to your stored procedure will not cause a SQL Injection attack.
However, depending on how you use stringInput in your stored procedure, you could still leave yourself open to an attack. Specifically, if you use stringInput in a dynamic SQL statement that you execute, you are leaving yourself open to attack. If you use it to do a compare in the WHERE section of a SELECT statement you should be safe.
It really depends on what you are doing inside of your stored proc. Simply by using stored procs, you are not immune to SQL Injection. Conversely, by using variables in your LINQ to Entity code, you are safe from SQL Injection because the query is parameterized correctly there as well. Unfortunately, full text indexing is not supported in Entity Framework, so you will need to resort to procs or functions to use them for performance concerns. I wouldn't say that it is necessarily more "elegant" than a LINQ generated query however.
I am working on window application developed using SCSF and we are using sybase database. As practise we create typedataset in the .net project and then populate them using framework method and for all the sql statement we write stored procedure in the database.
So we have type dataset in memory so I am using linq to select records from datatable. Can I step one step further and use something related to Entity Framework?
Can it reduce my work? I don't have hands-on experience with Entity Framework but can you suggest something in this scenario?
Thanks,
Denish
Entity framework uses similar concepts as the type datasets except for:
The ability to have a class structure that is not exactly the same as the table structure (e.g. class hierarchy, splitting tables into multiple classes, joining tables into one class).
The ability to use LINQ to perform queries in the database instead of in memory.
Entity framework also lets you map results of stored procedures to classes and bring results into memory if you need to run a query that is faster in memory or not translatable to SQL.
For most SQL queries the LINQ to Entity will be effective enough, so you will probably end up writing less stored procedures.
You will have to learn how to use EF and LINQ effectively and use can use 3rd party tools such as Entity Framework Profiler to help you.
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 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.