Problem statement.
Basically I get 3 - 50 parameters that come back from a web service as a NVP array I then need to loop over them create the SQL command parameters for each and call the stored procedure. Is there a more efficient way to handle it than the approach below?
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand cm = connection.CreateCommand())
{
cm.CommandText = "MySproc";
cm.CommandType = CommandType.StoredProcedure;
foreach (var field in row)
{
cm.Parameters.AddWithValue("#" + field.Key.ToString(), field.Value.ToString());
}
cm.ExecuteNonQuery();
}
}
I personally use the ISNULL or COALESCE in the WHERE clause of the stored procedure. Unless your looking to do it inside your c#...
http://blogs.x2line.com/al/archive/2004/03/01/189.aspx
Related
I have a task to develop a console application that is a recon of values from a few tables in the DB. I have all the queries that I need for each value that is required and understand the logic on how the values will interact. The challenge I have is the best method to retrieve and store these values.
I have researched and successfully been able to create the static method to retrieve a single value from a single SQL query but I'm curious about the best method:
Create multiple methods to retrieve each value (upwards of 15 different select statements) summarised below (not complete code)
static double total1(int arg)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command1 = new SqlCommand(commandText1, connection));
return(response);
}
}
static double total2(int arg)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command2 = new SqlCommand(commandText2, connection));
return(response);
}
}
Try to combine all select statements in a single method (I've been unsuccessful here) summarised below (not complete code)
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command1 = new SqlCommand(commandText1, connection))
{
}
using (SqlCommand command2 = new SqlCommand(commandText2, connection))
{
}
// etc
}
Create stored procedures in SQL and execute them and pass the parameters via the c# console app
I think method 1 is going to be taxing on the server as it would require the connection to open and close multiple times (although I don't know if that's as big a issue as I think it is). Method 2 seems more reasonable although I've followed the concepts here and I get stuck when trying to get the output of the commands (I'm using return). Method 3 seems smarter to me although I'd still be in a position where I need to choose between methods 1 & 2 to execute the SP's.
I would really appreciate advice and guidance here, I'm new to C# so this is a steep learning curve when tutorials don't cover the sort of thing (or at least I can't define my problem properly)
string query = "SELECT * FROM table1;";
query += "SELECT * FROM table2";
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(query))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
sda.Fill(ds);
}
}
}
}
I've recently seen that this question is still being viewed so I'll post the solution for anyone who is just starting off developing and encounters a similar challenge.
The most suitable solution was to create a stored procedure, pass each unique argument to it and return all the relevant data in a single response to the application. A custom model was defined for this output and the application logic adapted accordingly. The result is a longer running single call to the database as opposed to multiple individual ones.
Using the format from the question, the solution was:
C# code
static NewModel AllTotals(int arg1, int arg2)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
var commandText = "TheStoredProcName";
SqlCommand command = new SqlCommand(commandText, connection));
command.CommandType = System.Data.CommandType.StoredProcedure;
Cmd.Parameters.AddWithValue("#arg1", arg1);
Cmd.Parameters.AddWithValue("#arg1", arg2);
using (SqlDataReader dr = Cmd.ExecuteReader())
{
while (dr.Read())
{
var response = new NewModel(){
Value1 = Convert.ToDecimal(dr["value1"]),
Value2 = Convert.ToDecimal(dr["value2"]),
};
return(response);
}
}
}
return null;
}
SQL Stored Proc
CREATE PROCEDURE [dbo].[TheStoredProcName]
#arg1 int,
#arg2 int
AS
DECLARE #value1 decimal(18,6) = ISNULL((--QUERY TO GET VALUE1),0)
DECLARE #value2 decimal(18,6) = ISNULL((--QUERY TO GET VALUE2),0)
-- select the variables into a result set for the application
SELECT #value1 as [value1], #value2 as [value2]
I have a stored procedure that looks like that:
InsertItem: INSERT INTO (IN itemId INT, name TEXT);
Is there a way I could execute a bulk of it?
like instead of executing something like that:
using (MySqlConnection connection = new MySqlConnection(_connectionString))
{
connection.Open();
foreach (Item item in GetItems())
{
using (MySqlCommand command = new MySqlCommand("InsertItem", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#itemId", item.ItemId);
command.Parameters.AddWithValue("#name", item.Name);
command.ExecuteNonQuery();
}
}
}
I'm trying to achieve code looking like that without successing:
using (MySqlConnection connection = new MySqlConnection(_connectionString))
{
connection.Open();
using (MySqlCommandBulk command = new MySqlCommand("InsertItem", connection))
{
command.CommandType = CommandType.StoredProcedure;
for (Item item in GetItems())
{
MySqlCommandBulkItem bulkItem = new MySqlCommandBulkItem();
bulkItem["itemId"] = item.ItemId;
bulkItem["name"] = item.Name;
command.BulkItems.Add(bulkItem);
}
command.Execute();
}
}
My point is that the command will send all of the data at once, and will not send each query alone.
Any ideas?
The Oracle connector for the Dotnet framework allows the use of arrays in place of scalars on parameters. But the MySQL connector doesn't.
There are two ways to accelerate bulk loads in MySQL.
One of them applies to InnoDB tables but doesn't help with MyISAM tables. Start a transaction. Then, after every few hundred rows, COMMIT it and start another one. That will commit your table inserts in bunches, which is faster than autocommiting them individually.
The other is to use MySQL's LOAD DATA INFILE command to slurp up a data file and bulk-insert it into the database. This is very fast, but you have to be diligent about formatting your file correctly.
I am quit busy turning a old classic asp website to a .NET site. also i am now using SQL Server.
Now I have some old code
strsql = "select * FROM tabel WHERE ID = " & strID & " AND userid = " & struserid
rs1.open strsql, strCon, 2, 3
if rs1.eof THEN
rs1.addnew
end if
if straantal <> 0 THEN
rs1("userid") = struserid
rs1("verlangid") = strID
rs1("aantal") = straantal
end if
rs1.update
rs1.close
I want to use this in SQL Server. The update way. How can I do this?
How can I check if the datareader is EOF/EOL
How can I insert a row id it is EOF/EOL
How can I update a row or delete a row with one function?
If you want to use raw SQL commands you can try something like this
using (SqlConnection cnn = new SqlConnection(_connectionString))
using (SqlCommand cmd = new SqlCommand())
{
cnn.Open();
cmd.Connection = cnn;
// Example of reading with SqlDataReader
cmd.CommandText = "select sql query here";
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
myList.Add((int)reader[0]);
}
}
// Example of updating row
cmd.CommandText = "update sql query here";
cmd.ExecuteNonQuery();
}
It depends on the method you use... Are you going to use Entity Framework and LINQ? Are you going to use a straight SQL Connection? I would highly recommend going down the EF route but a simple straight SQL snippet would look something like:
using (var connection = new SqlConnection("Your connection string here"))
{
connection.Open();
using (var command = new SqlCommand("SELECT * FROM xyz ETC", connection))
{
// Process results
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
int userId = (int)reader["UserID"];
string somethingElse = (string)reader["AnotherField"];
// Etc, etc...
}
}
}
// To execute a query (INSERT, UPDATE, DELETE etc)
using (var commandExec = new SqlCommand("DELETE * FROM xyz ETC", connection))
{
commandExec.ExecuteNonQuery();
}
}
You will note the various elements wrapped in using, that is because you need to release the memory / connection when you have finished. This should answer your question quickly but as others have suggested (including me) I would investigate Entity Framework as it is much more powerful but has a learning curve attached to it!
You can use SQL store procedure for Update. And call this store procedure through C#.
Create procedure [dbo].[xyz_Update]
(
#para1
#para2
)
AS
BEGIN
Update tablename
Set Fieldname1=#para1,
Set Feildname2=#para2
end
I have a method which contains a very big sql query directly in the .CS file. What would the recommended refactoring method be?
You could put the large complex SQL query into a SQL View or Stored Procedure, and just use that in the code.
You should use stored procedure
string commandText = "SP_Your_Sp_Name";
using (SqlConnection objSqlConnection = Connection)
{
using (SqlCommand cmd = new SqlCommand(commandText, objSqlConnection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#Parameter_Name", value));
if (cmd.Connection.State != ConnectionState.Open)
{
cmd.Connection.Open();
}
result = (string)cmd.ExecuteScalar();
}
}
Use a stored procedure.
In this case the query execution will be faster when the execution plan is stored in the cache.
Is this code safe from SQL injections? Why?
public void AddPlayer(string username)
{
var query = "INSERT INTO dbo.Player(Username, RegisterDate) VALUES(#Username, #RegisterDate)";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#Username", username);
command.Parameters.AddWithValue("#RegisterDate", DateTime.Now);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
public DateTime GetRegisterDate(string username)
{
var query = "SELECT RegisterDate FROM dbo.Player WHERE Username = #Username";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#Username", username);
command.Connection.Open();
return (DateTime)command.ExecuteScalar();
}
}
EDIT: Could injection-safe equivalent code be written using a stored procedure? If so, what the stored procedure would be like?
Yes, It looks safe.
Because it uses parameters.
You run a risk of SQL-injection when you create queries like
baseQueryText + " WHERE Username =" + TextBox.Text;
Reguarding the Edit: When you use a Stored Procedure you always use parameters so they are safe too. No special effort required, but you still could/should filter incoming data.
Yes. You are using parameterized queries, which are in general considered safe from SQL injection.
You may still want to consider filtering your inputs anyway.
Yes, all the non-static data is being fed in via bound parameters.