How to call multiple stored procedures in a MySql database - c#

I am able to get this program to work with one stored procedure. Is it possible to call multiple stored procedures from MYSQL in C#? If so what is the most efficient way of doing so? Here is a snippet of my code to show what I've done thus far:
public static string RunSQL()
{
// Here is where it is connecting to local host.
string connStr = "server=localhost;user=xxxx;"
+ "database=xxxx;port=3306;password=xxx;"
+ "Allow User Variables=True";
MySqlConnection conn = new MySqlConnection(connStr);
// Here is where the connection gets opened.
conn.Open();
// Here I call the CN_renumber stored procedure.
MySqlCommand CN_renumber = new MySqlCommand("CN_renumber", conn);
CN_renumber.CommandType = System.Data.CommandType.StoredProcedure;
object result = CN_renumber.ExecuteNonQuery();
// Disconnect from local host.
conn.Close();
return result.ToString();
}

You can reuse your object of MySQLCommand multiple times, but before that you should make sure you call myCommand.Parameters.Clear();, then assign the new Stored Procedure name again.
Useful question with example here

Related

Could not find stored procedure error when using username password combination

I am trying to call a stored procedure from my C# code and passing table parameters using the user-defined table types.
This works perfectly fine when I use the Trusted_Connection= True; method in the connection string. However, when I update the connection string to use the service account username password combination, I get the following error:
Could not find stored procedure 'usp_MyTestSP'
By the way, here is the code I'm using to call that stored procedure and passing the table parameters:
// Works fine with this connection string
var conString = "Data Source=xxx;Initial Catalog=xxx;Trusted_Connection=True;";
// Fails when using a service account in connection string. Error: Could not find stored procedure 'usp_MyTestSP'
//var conString = "Data Source=xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx";
using (var con = new SqlConnection(conString))
{
var cmd = new SqlCommand("usp_MyTestSP", con) {CommandType = CommandType.StoredProcedure};
var myParams = new SqlParameter()
{
ParameterName = "#udt_RecordProcessed",
Value = myVal
};
cmd.Parameters.Add(myParams);
con.Open();
cmd.ExecuteNonQuery();
}
Is it really the permission thing?
When I connect to the SQL Server instance using the custom service account, I am actually able to view that stored procedure that the code is complaining about not being able to find.
Do I need some additional permissions here for my service account to be able to execute that stored procedure?
Or... is there something I need to update in my code for it to work with the service account? Although the same code works just fine with using the trusted connection.
Any input here would be really very helpful.
Thank you.
I think something is wrong in your code with the connection string set to the SqlConnection instance, you must use conString variable instead of the cs variable:
using (var con = new SqlConnection(conString))
I was able to get this working by adding the [db_owner] prefix to the stored procedure name usp_MyTestSP as shown in the following code:
// Works fine with this connection string
var conString = "Data Source=xxx;Initial Catalog=xxx;Trusted_Connection=True;";
// Fails when using a service account in connection string. Error: Could not find stored procedure 'usp_MyTestSP'
//var conString = "Data Source=xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx";
using (var con = new SqlConnection(conString))
{
// ** The fix was to prefix the stored procedure name with [db_owner]
var cmd = new SqlCommand("[db_owner].[usp_MyTestSP]", con) {CommandType = CommandType.StoredProcedure};
var myParams = new SqlParameter()
{
ParameterName = "#udt_RecordProcessed",
Value = myVal
};
cmd.Parameters.Add(myParams);
con.Open();
cmd.ExecuteNonQuery();
}

Open MSQL procedure from C# application (using System.Diagnostics)

I am having difficulties in finding a solution for opening a stored procedure straight to MSQL management studio for modifying in a new SQLQuery from my C# application (winform).
Here is my code:
Process openSQL = new Process();
openSQL.StartInfo.FileName = "Ssms.exe";
openSQL.StartInfo.Arguments = "dbo.getResults"; //name of the stored procedure I want to open
openSQL.Start();
I am getting error after executing the code :"The following files were specified on the command line: dbo.getResults These files could not be found and will not be loaded."
How am I supposed to "point" to the stored procedure in C# and get its definition displayed and ready to get modifications in MSQL management studio?
This isn't possible I'm afraid. If you run ssms -? from the command line you can see all the parameters that you can pass in:
Some options:
Let users edit procs themselves. After all, anyone capable of doing this will understand how to use SSMS properly.
Make your own UI. You can read the contents of a stored procedure and display them in a text box. The downside is that you lose features such as syntax highlighting (unless you also build that in too)
You could download the procedure and store it in a procedure.sql file and get SSMS to open that. Don't forget to pass in the server, database and credentials.
I found a way to open a stored procedure script straight to MSQL management studio for modifying in a new SQLQuery from my C# application (winform).
I am taking the script of the procedure with EXEC sp_helptext 'procedure_name'
The result set is filled in a DataSet
And the DataSet is getting written in an empty .sql file
The .sql file is getting opened in MSQL Managment Studio with System.Diagnostics;
Here are the steps with code snippets:
private void saveProcToAFile()
{
StreamWriter log;
if (!File.Exists("procedureToBeLoaded.sql"))
{
log = new StreamWriter("procedureToBeLoaded.sql");
}
else
{
log = new StreamWriter(File.Create("procedureToBeLoaded.sql"));
}
SqlConnection conn = new SqlConnection(conString);
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = string.Format("EXEC sp_helptext '{0}'", "procedure_name"); //Step 1.
da.SelectCommand = cmd;
DataSet ds = new DataSet();
conn.Open();
da.Fill(ds); //Step 2.
conn.Close();
foreach (DataRow dr in ds.Tables[0].Rows)
{
log.WriteLine(dr[0]); //Step 3.
}
log.Close();
}
Step 4.
private void contextMenuStripOpenInSqlStudio_Click(object sender, EventArgs e)
{
saveProcToAFile();
Process openSQL = new Process();
openSQL.StartInfo.FileName = "Ssms.exe";
openSQL.StartInfo.Arguments = "procedureToBeLoaded.sql";
openSQL.Start();
}

C# Using multiple MySQL connection or put queries in queue to execute respectively

I have a client/server app and my server stores data in a MySQL database, currently I have made a connection and I do queries without queue or something. I don't think this is a good solution for this, because when a MySQLDataReader opens another one can't be execute at the same time and first one must be closed. I think I have two options, either make a connection by every DataReader or put my queries in a queue to execute them one by one.
I want to know which one is the best or is there any way or something to prevent errors and exception which causes this error
There is already an open DataReader associated with this Connection which must be closed first.
This is how currently I am doing queries. I first get the main connection and do queries. it my causes above error.
string query = "SELECT * FROM users WHERE username = #username";
ServerModel.Database.CheckConnection(); // Get the main connection
MySqlCommand cmd = new MySqlCommand(query, ServerModel.Database);
cmd.Parameters.AddWithValue("#username", username);
UserStatus userStatus;
using (MySqlDataReader dataReader = cmd.ExecuteReader())
{
if (dataReader.Read())
{
...
dataReader.Close();
return userStatus;
}
}
To note that this server may do thousands of queries at moment. think about a chat server.
In this case please don't use the using block, I hope below approach will work fine.
string query = "SELECT * FROM users WHERE username = #username";
ServerModel.Database.CheckConnection(); // Get the main connection
MySqlCommand cmd = new MySqlCommand(query, ServerModel.Database);
cmd.Parameters.AddWithValue("#username", username);
UserStatus userStatus;
MySqlDataReader dataReader = cmd.ExecuteReader()
if (dataReader.Read())
{
...
dataReader.Close();
return userStatus;
}

C# Reusable Mysql Class

I am having some issues with a class that I have created to perform different database commands.
1st) The program is local ran, and will only run locally. It will only ever connect to the database on the localhost.
Therefore I have a simple class setup, called databaseConnector that allows me to pass a string to it with the required Mysql query to perform the different functions.
For instance.
I use:
var db = new databaseConnector();
db.Update("UPDATE * WHERE.....");
However, it seems if I ever want to use a different query, or another query, it's not working and throwing errors.
For instance.
var db = new databaseConnector();
db.Update("UPDATE * WHERE...");
db.INSERT("INSERT INTO * WHERE.....");
Will give me an error on the insert execution. Any ideas why? I have resorted to creating it again. So I have to redo:
db = new databaseConnector();
to then use the Insert command.
Here is an example of my insert function.
public void Insert(string query)
{
//open connection
if (this.OpenConnection() == true)
{
//create command and assign the query and connection from the constructor
MySqlCommand cmd = new MySqlCommand(query, connection);
//Execute command
cmd.ExecuteNonQuery();
//close connection
this.CloseConnection();
}
}
Now that I think about it. Should I call my db.openConnection() before doing it. Since when I initialize it in the first var db = new databaseConnection(), it's opening? And then in each function it's closing it, but only checking if it's open, instead of attempting to open, doing query, then closing.

Dropping SQL Server database through C#

I am using this code to delete a database through C#
Int32 result = 0;
try
{
String Connectionstring = CCMMUtility.CreateConnectionString(false, txt_DbDataSource.Text, "master", "sa", "happytimes", 1000);
SqlConnection con = new SqlConnection();
con.ConnectionString = Connectionstring;
String sqlCommandText = "DROP DATABASE [" + DbName + "]";
if (con.State == ConnectionState.Closed)
{
con.Open();
SqlConnection.ClearPool(con);
con.ChangeDatabase("master");
SqlCommand sqlCommand = new SqlCommand(sqlCommandText, con);
sqlCommand.ExecuteNonQuery();
}
else
{
con.ChangeDatabase("master");
SqlCommand sqlCommand = new SqlCommand(sqlCommandText, con);
sqlCommand.ExecuteNonQuery();
}
con.Close();
con.Dispose();
result = 1;
}
catch (Exception ex)
{
result = 0;
}
return result;
But I get an error
Database currently in use
Can anyone help?
Try this:
String sqlCommandText = #"
ALTER DATABASE " + DbName + #" SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [" + DbName + "]";
Also make sure that your connection string defaults you to the master database, or any other database other than the one you're dropping!
As an aside, you really don't need all of that stuff around your queries. The ConnectionState will always start off Closed, so you don't need to check for that. Likewise, wrapping your connection in a using block eliminates the need to explicitly close or dispose the connection. All you really need to do is:
String Connectionstring = CCMMUtility.CreateConnectionString(false, txt_DbDataSource.Text, "master", "sa", "happytimes", 1000);
using(SqlConnection con = new SqlConnection(Connectionstring)) {
con.Open();
String sqlCommandText = #"
ALTER DATABASE " + DbName + #" SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [" + DbName + "]";
SqlCommand sqlCommand = new SqlCommand(sqlCommandText, con);
sqlCommand.ExecuteNonQuery();
}
result = 1;
Here is how you do it using Entity Framework version 6
System.Data.Entity.Database.Delete(connectionString);
You should take a look at SMO.
These allow you to manage all aspects of SQL Server from code, including deleting of databases.
The database object has a Drop method to delete database.
Create sqlconnection object for different database other than you want to delete.
sqlCommandText = "DROP DATABASE [DBNAME]";
sqlCommand = new SqlCommand(sqlCommandText , sqlconnection);
sqlCommand.ExecuteNonQuery();
In this case i would recommend that you take the database offline first... that will close all connections and etc... heres an article on how to do it: http://blog.sqlauthority.com/2010/04/24/sql-server-t-sql-script-to-take-database-offline-take-database-online/
Microsoft clearly states that A database can be dropped regardless of its state: offline, read-only, suspect, and so on. on this MSDN article (DROP DATABASE (Transact-SQL))
Connection pooling at a guess, use sql server's activity monitor to make sure though.
Pooling keeps connections to the database alive in a cache, then when you create a new one, if there's one in the cache it hands it back instead of instantiating a new one. They hang around for a default time, (2 minutes I think) if they don't get re-used in that time, then they killed off.
So as a first go connect straight to master, instead of using change database, as I suspect change database will simply swap connections in the pool.
Add a check routine for database in use (use a connection to master to do it!). You can force the database to be dropped anyway by first executing
ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
again from the connection to master!
However everybody else using the db, will no longer like you at all...
Just don't use DB name in connection string.
"Data Source=.\SQLEXPRESS;Integrated Security=True;"
I was having the same troubles as Anshuman...
By my testing of the code in question of Anshuman there have been very simple error:
there have to be SqlConnection.ClearAllPools(); instead of SqlConnection.ClearPool(con);
Like this trouble of
"cannot drop database because is in use..."
disappears.

Categories

Resources