Getting data into and out of SQL tables with C#
I built a C# app that puts data into a SQL table.
I am currently using the SqlConnection class in .net.
Got started with this article.
http://www.codeproject.com/KB/database/sql_in_csharp.aspx
I had thought about looking at Linq to SQL but have not done it before and wasn't sure how to get up and going.
Well today I ran across a bug where I was trying to add data that include a "'" in it which broke my insert statement. I got to doing some research and am starting to wonder what other problems are lurking. What if I try to add the data "drop table"?
My question is, is there a better model for data insertion? Do I look at Linq? Or do I check all my data before it is entered?
You discovered SQL Injection Attacks. It is not good policy to just append user supplied data to a SQL query for exactly the reason you specified. Any user of your system could try to steal or corrupt your data by injecting some SQL.
The way to deal with it is described in the link, but basically you specify the parameters and let the supplied classes handle properly escaping the data so that if someone passes "Drop Table", it will simply be entered as data.
Here's a great example from CodeBetter.com
SqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Customers WHERE CustomerID = #CustomerID";
command.Parameters.Add(
new SqlParameter("#CustomerID", SqlDbType.NChar, 5)).Value = customerID;
Alternatively, feel free to use LINQ to SQL. It will handle this for you and is much easier to work with from a developer perspective. You can drag and drop your database into your code and it will completely map every table. Then you can write LINQ's version of SQL statements right in your code where you'll get code completion and Compile time checking for errors. This SO question will get you started.
Here's some simple LINQ code that lets you read a customer from the database, write his/her name to the screen, then update his personalized greeting (all safe from SQL injection):
Customer myCustomer = (
from cust in myDatabase.Customers
where cust.CustomerID == userPassedCustomerID
select cust).Single();
Console.WriteLine(myCustomer.FullName);
myCustomer.PersonalizedGreeting = userPassedGreeting;
myDatabase.SubmitChanges();
The best way to work with database queries that need to be mingled with user input is to parameterized them. Now LINQ to SQL will do this for you but plain old ADO.NET lets you do it too (as the article I linked describes).
This works whether you are calling stored procedures or creating dynamic queries in your application to send to your RDBMS.
It appears you were doing some dynamic SQL, i.e. creating SQL statements on the fly, using various string manipulations in C# and then running these.
This way of doing is very versatile but introduces the risk of SQL injection. This was an accidental situation, self inflicted, but assuming that some of the elements used in building the SQL statement are provided by way of html fields, an malicious user could craft a particular string to effectively "DROP TABLE" or worse...
There are many ways to work around this situation, the most common one being to use parametrized SQL templates. With this technique, the variable parts of a SQL statement are provided to SQL in separate arguments (called parameter at the level of SQL). The ADO Command object is the vehicle used for invoking parametrized queries.
LINQ to SQL could also be used to handle this type of thing as well.
Related
I'm using EF 6 to model an Oracle database and in turn wrote a simple LINQ to SQL statement to pull data. If I take the query object and do something like:
linqQuery.ToString()
I'll get the SQL but it has placeholders rather than the conditions passed in by my variables. I've searched around but I can't see any solution. The purpose of this use case is to use EF to model my entities, LINQ to SQL to craft the SQL which I then plan to hand off to another process.
Is there anyway of getting my SQL generated to include the variables?
You should be able to use the logging facilities to get the exact complete SQL that is sent to the underlying RDBMS. Yes, it will contain parameters, but the definitions and values of the parameters should be part of that.
See https://msdn.microsoft.com/en-us/library/dn469464%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396
I have around 500 stored procedures that are used for our ETL process. I have been asked to identify all the source and target tables used by each stored procedure. So, a stored procedure could have a connection to an Oracle linked server, or another SQL Server. It could also be using an OPENQUERY to extract data from our transactional systems.
Since I have some basic .NET/C# programming chops, I was hoping to leverage the .NET RegEx class to get started. However, I am looking for suggestions on how I should approach this. I really don't have to reinvent the wheel if someone already has a solution for this.
As a context, we are working on implementing PowerDesigner to store metadata repository. So, we are looking to extract metadata from our BI reports (map reports to it's source tables/views) and our Informatica and T-SQL ETL scripts.
Thanks
I'd suggest a dual-approach. Firstly, I'd avoid using regex for something as complex as SQL Query parsing, especially since there are tools in place for this kind of thing.
https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.dependencywalker.aspx
The SMO library exposes a class that will let you connect to a server and retrieve a dependency tree for a given stored procedure. How to do this exactly is left as an exercise for the reader :)
However, this class won't pick up dependencies that are introduced via dynamic SQL or through OPENQUERY. If the number of procedures that do this are small, I'd recommend doing this manually, and then merging the results. You could use the SMO scripting capabilities to pick up all instances of either OPENQUERY or exec/sp_executesql; at least then you would have an idea of 'suspect' pieces of code.
Merging the results will be tricky. Not only do you have to manually update dependencies for procedures containing dynamic dependencies, but you have to update procedures that depend on procedures containing dynamic dependencies.
You can use a dynamic management view dm_sql_referenced_entities to get some dependency information from SQL Server itself but there are some limitations. Not sure if the Dependency Walker leverages this view, but the pros and cons are very similar.
The same main limitation that I know of and have experienced is that you won't get any dependency information for an object that is leveraged through dynamic sql. We have very contained usages of dynamic sql so I can feel pretty confident leveraging this DMV and manually accounting for the objects hit by those specific procs.
We don't do linked servers, but in my understanding is that those would show in this DMV. I don't know about the OPENQUERY ... I did a little bit of research but I did not test it out but I am guessing those would not be surfaced by the view. Like the previous poster said, you may need a two-pronged approach to get everything you're looking for.
And just for reference, a simple example of using that DMV:
SELECT DISTINCT
[database] = COALESCE(r.referenced_database_name, DB_NAME())
, [schema] = r.referenced_schema_name
, name = r.referenced_entity_name
, r.referenced_id
FROM sys.dm_sql_referenced_entities('dbo.procName_sp', 'OBJECT') AS r
WHERE r.referenced_id IS NOT NULL;
I wouldn't use C# for this. However, maybe something like this will do the job.
select *
from DatabaseName.information_schema.routines
where routine_type = 'PROCEDURE'
SELECT name, type
FROM dbo.sysobjects
WHERE type IN (
'P', -- stored procedures
'FN', -- scalar functions
'IF', -- inline table-valued functions
'TF' -- table-valued functions
)
ORDER BY type, name
Or, if you want SProcs and parameters:
select * from information_schema.parameters
Finally, this link looks pretty helpful for your situation.
http://blog.sqlauthority.com/2010/02/04/sql-server-get-the-list-of-object-dependencies-sp_depends-and-information_schema-routines-and-sys-dm_sql_referencing_entities/
I'm looking for a class for Sql Server. I need to make insert, update, delete, select (retrieve many rows and columns) and execute Stored Procedure.
I didn't find a sample of this sort of class and i didn't want to reinvente the wheel.
Somebody can give it to me?
You sound like you may be looking for a ORM (Object Relational Mapper). There are a great number available, some built right it to the .NET framework itself. Look at the various websites and see if you can find one that fits your needs.
There's not a single class that does this, but instead a set of a few classes you need to know:
Sql Server specific:
System.Data.SqlClient.SqlConnection
System.Data.SqlClient.SqlCommand
System.Data.SqlClient.SqlDataReader
System.Data.SqlClient.SqlDataAdapter
System.Data.SqlClient.SqlParameter
Used by all database types
System.Data.DataTable
System.Data.DataSet
System.Data.SqlDbType (enum)
There are others as well, but these are the main ones. Together, these make up the ADO.Net API, and the Sql Server provider for the ADO.Net API.
Additionally, there are a number of Object Relational Mappers that build on top of ADO.Net to try to make this easier. Entity Framework, Linq To Sql, and NHibernate are of a few of the more common options. One common characteristic of ORMs is that they try to free you from even knowing the sql language. If you want to write your own SELECT/INSERT/UPDATE/DELETE queries, which it sounds like you do, you should start at the native ADO.Net level.
To put your data access in one object, you create your own class that makes use of these other types. Don't try to build a new public method that accepts an sql string. Build individual methods for each query you will want to run that include the needed sql as part of the method, and have those methods use these types to change or return data.
You might be interested in this tutorial.
There is builtin functionality (System.Data.SqlClient) to simply access an SQL server.
There is no single class that can do everything you need. Whatever choice you decide you would necessarily need to deal with multiple classes.
Look at it this way – in order to get data from SQL Server you need to typically do following things:
Open connection
Crete SQL query
Execute SQL Query
Accept results
Close connection
Putting all this functionality into a single class would make the class way too complex.
Here is a good reading material for what you need.
Beginners guide to accessing SQL Server through C#
I have an .NET application which is running the following statement using SqlCommand:
DECLARE #SQL VARCHAR(100)
SELECT #SQL = 'CREATE DATABASE ' + #DB
EXEC(#SQL)
The #DB parameter comes from user input, so obviously the application is vulnerable to something like 'X DROP DATABASE Y'. I'm sure there must be an obvious way I'm missing...
Edit: using a parametrized statement cannot work because you cannot use a parameter in CREATE DATABASE (CREATE DATABASE #DB returns a syntax error).
First, you should never, ever do this from a web app. Ever. Really. I'm serious. With the exception of deployment packages, the only time I've needed to execute a CREATE DATABASE is from the query analyzer in SSMS. Additionally, I'm suspicious of any code that would let a user enter a database name, and then go and create it.
Most importantly, what you've posted is not a "parameterized query." It's concatenated SQL, which is the source of SQL injection vulnerabilities.. If it were a parameterized query (or a stored proc, but I don't think you can do a CREATE DATABASE from a sproc), SQL injection would be a non-issue.
You can either use a real parametrized query (here is a good tutorial on parametrized queries.), or sanitize your inputs, but ADO.NET or whatever other db library will reliably handle this for you IF you properly build the command and parameter objects.
You probably want to specify parameters - paramaterized queries pretty much eliminate SQL injection attacks (as long as you're not concatenating strings in your receiving stored procedures).
Like I said in my comment, I hope there's an exceptionally good reason for creating databases/tables on the fly where creating rows seems to work for most everyone else.
Use a whitelist approach: allow only letters.
I need to run sql statements from the application itself. i.e. the user can go into the asp.net applciation, gets a box and can run sql statements from there
I am already doing something like this
Can I rollback Dynamic SQL in SQL Server / TSQL
That is running dynamic sql
is there a better way to do this
Dynamic SQL is certainly the easiest way to do this. The alternative is parameterized SQL, but that would require having your users define and set parameters separately from the T-SQL.
You can simply submit the T-SQL string to SQL Server using the SqlCommand object; there's no real benefit to wrapping it in an EXEC or anything, as in the link you provided. You can do exception handling on the .NET side.
Also, if you want to support command batches, keep in mind that SqlClient and friends don't understand "GO", which also isn't an actual T-SQL command -- you will need to parse the input and break it into batches yourself.
I'm sure you understand that there is a big security risk in doing this, and that's it's generally not recommended. You might consider using a connection string that specifies a user with limited permissions, to help control / limit their access.
DO NOT DO THIS. What if the user types in sp_msforeachtable 'truncate table ?'...?
RunSQL.aspx utility might help. See Upload T-SQL and execute at your hosting provider using an ASP.NET page.