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.
Related
I'm writing a library that requires the use of a recursive (CTE) query to efficiently fetch some data. Obviously this is not possible to do using Entity Framework and LINQ. As a result, I have used the FromSql command to run the raw query against the database. However, my query was designed and works against MySQL/MariaDB. When I run it against postgres, there are some minor syntax differences that cause it to break.
Ideally, I would like to avoid hardcoding (copy and pasting) the same query 3 times to work with postgres, mysql and potentially MS SQL. Given a DbContext is there any way I can drill down and get specific SQL syntax information from the underlying provider? For example MySQL uses a backtick as a quoted identifier, and Postgres uses double quotes, MS SQL is wrapped in [ and ]. Is there any way I can fetch this type of information from the underlying provider to hopefully make my FromSQL raw query as robust as possible?
All which comes to my mind in EF Core 2.x is the ISqlGenerationHelper interface (service). It's quite limited, but provides DelimitIdentifier method which does what you are asking for. And is used by the DefaultQuerySqlGenerator shared by all provider SQL generators, so I guess it should be enough.
Since this is internal service, you'd need
using Microsoft.EntityFrameworkCore.Infrastructure;
in order to get access to GetService extension method, and
using Microsoft.EntityFrameworkCore.Storage;
for ISqlGenerationHelper interface.
The usage is like this:
var sqlGeneratorHelper = dbContext.GetService<ISqlGenerationHelper>();
var tableName = sqlGeneratorHelper.DelimitIdentifier("MyTable");
// SqlServer: [MyTable]
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 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.
How do you write a stored procedure using C# in SQLCLR?
Currently I am using SQL Server Management Studio and I write stored procedures using T-SQL such as create proc sp_item as .....
See:
Building my first SQL CLR stored procedure
CLR Assembly RegEx Functions for SQL Server by Example
Choosing between CLR and T-SQL stored procedures: a simple benchmark
Basically, there are Visual Studio templates which allow you to get started with SQL CLR projects. Fill in the blanks, write your actual code, and you can even deploy those CLR assemblies into SQL Server directly from within Visual Studio.
One word of caution: I would refrain from doing set-based updates and inserts and stuff like that in a SQL CLR stored proc - for that, T-SQL stored procs are just plain better and faster.
SQL-CLR is great to extend SQL Server with stuff like string manipulation, date handling, ability to call e.g. web services or other stuff. I would recommend against trying to replace all T-SQL stored procs with C# SQL CLR stored procs just because you can or just because it's cool - use the right tool for the right job! Mass operations on sets are better left to T-SQL.
In addition to the links provided by Marc, I also wrote a short tutorial on writing SQLCLR Table-Valued Functions (FYI, free registration is required to view articles on SQL Server Central):
CLR Table-Valued Function Example with Full Streaming (STVF / TVF)
I have also been writing a series of articles about working with SQLCLR in general:
Stairway to SQLCLR
Also, you should not use sp_ as a prefix in stored procedure names. That is a special syntax that degrades performance due to causing SQL Server to first check for that stored procedure in master, and then, if not found there, it will search the current database.
I am using sql server and winforms for my application. data would be inserted every minute into the database tables by pressing a button on a Form.
for this, I am using the INSERT query.
But if I create a procedure and include the same insert query in it, then would it be more efficient, what would be the difference then?
Using stored procedures is more secure
A stored procedure would generally be quicker as the query plan is stored and does not need to be created for each call. If this is a simple insert the difference would be minimal.
A stored procedure can be run with execute permissions which is more secure than giving insert permissions to the user.
It depends on what you mean by 'efficient'.
Execution time - if you're only saving to the database only every couple of seconds then any speed difference between SPs and INSERT is most likely insignificant. If the volume is especially high you would probably set up something like a command queue on the server before fine-tuning at this level.
Development time
using INSERT means you can write your SQL directly in your codebase (in a repository or similar). I've seen that described as poor design, but I think that as long as you have integration tests around the query there's no real problem
Stored Procedures can be more difficult to maintain - you need to have a plan to deploy the new SP to the database. Benefits are that you can implement finer-grained security on the database itself (as #b-rain and #mark_s have said) and it is easy to decide between INSERT and UPDATE within the SP, whereas to do the same in code means making certain assumptions.
Personally (at the moment) I use inline SQL for querying and deleting, and stored procedures for inserting. I have a script and a set of migration files that I can run against the production database to deploy table and SP changes, which seems to work pretty well. I also have integration tests around both the inline SQL and the SP calls. If you go for inline SQL you definitely should use parameterised queries, it helps against SQL injection attacks and it is also easier to read and program.
If your DBA is even allowing you to do this without a stored procedure I'd be very suspicious...