I have 5 parameters and I want to send them to the method:
public static SqlCommand getCommand(string procedure, SqlParameter[] parameter)
{
Sqlcommand cmd;
return cmd
}
Can I send these paramters at one time like this?
SqlParameterCollection prm;
prm.Add(p1);
prm.Add(p2);
prm.Add(p3);
prm.Add(p4);
prm.Add(p5);
sqlcommand cmd = getCommand(prm);
Or create an array of parameters by hand:
SqlParameter[] parameter = {
new SqlParameter(...),
new SqlParameter(...),
new SqlParameter(...)
};
But I don't see what should be wrong with your approach. It simple, readable and understendable.
I don't see what's wrong with that? You do know that, if this is .NET, you need to attach the parameters to the SqlCommand object?
So:
SqlCommand query = new SqlCommand(sqlString, Connection);
query.Parameters.AddWithValue(parameter,valueToPass);
etc?
Sorry if that's not related, not completely sure on your question? Your method doesn't really do anything, I take you left out the code and just put in a dummy for the purposes of asking the question? You can pass an array as an arguement so you just need to spilt it up?
Using this as inspiration, this code worked for me:
List<SqlCeParameter> parameters = new List<SqlCeParameter>();
parameters.Add(new SqlCeParameter("#Username", NewUsername));
parameters.Add(new SqlCeParameter("#Password", Password));
cmd.Parameters.AddRange(parameters.ToArray());
Well, that won't compile because in your call to getCommand you're not passing in a string with the procedure, but as far as the array, that should work no problem.
Here is my code.You can use all parameter properties like name,value,type etc.
int SelectedListID = 6;
string selectedPrefix = "IP";
string sqlQuery = "select * from callHistory where ImportID=#IMPORTID and Prefix=#PREFIX"
SqlParameter[] sParams = new SqlParameter[2]; // Parameter count
sParams[0] = new SqlParameter();
sParams[0].SqlDbType = SqlDbType.Int;
sParams[0].ParameterName = "#IMPORTID";
sParams[0].Value = SelectedListID;
sParams[1] = new SqlParameter();
sParams[1].SqlDbType = SqlDbType.VarChar;
sParams[1].ParameterName = "#PREFIX";
sParams[1].Value = selectedPrefix;
SqlCommand cmd = new SqlCommand(sqlQuery, sConnection);
if (sParams != null)
{
foreach (SqlParameter sParam in sParams)
{
cmd.Parameters.Add(sParam);
Application.DoEvents();
}
}
Form1.cs
static private void FunctionCall()
{
string connectionString = "DATA Source=nwind;server=GRAPHICS\SQLEXPRESS;Persist Security Info=False;Integrated Security=SSPI;Connect Timeout=30";
string sSqlQuery;
DataSet ds;
DataTable dt;
// Prepare SQL Query
sSqlQuery = #"
select content " +
"from " +
"[TBL] where id = '000-000'";
SqlParameter[] sqlParams = {
new SqlParameter("",SqlDbType.Int),
new SqlParameter("",SqlDbType.VarChar),
new SqlParameter("",SqlDbType.VarChar)
};
// Read from database
ds = SqlHelper.ExecuteNonQuery(connectionString, sSqlQuery, CommandType.Text, sqlParams);
dt = ds.Tables[0];
}
SqlHelper.cs
// Executes a non query
public static int ExecuteNonQuery (string connectionString, string cmdText, CommandType type, SqlParameter[] prms)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(cmdText, conn))
{
cmd.CommandType = type;
if (prms != null)
{
foreach (SqlParameter p in prms)
{
cmd.Parameters.Add(p);
}
}
conn.Open();
return cmd.ExecuteNonQuery();
}
}
}
1.
public IEnumerable<SqlParameter> GetAndSetParameters(List<Tuple<string, string>> parameters){
List<SqlParameter> paramlist = new List<SqlParameter>();
foreach (var item in parameters)
{
paramlist.Add(new SqlParameter(item.Item1, item.Item2));
}
return paramlist;
}
2. pass parameters
public List<Tuple<string, string>> GetUserParameter(){
List<Tuple<string, string>> list = new List<Tuple<string, string>>();
list.Add(new Tuple<string, string>("#User",user.UserID));
return list;
}
3. finally use it:
SqlCommand oCmd = new SqlCommand(oString, myConnection);
oCmd.Parameters.AddRange(GetAndSetParameters(GetUserParameter()).ToArray());
Related
I have a method that returns a string from a database based on what i pass to it. The method works but i need to display the result in a textbox on a form. But when i run it the result i keep getting is "System.Collections.Generic.List`1[System.String]". I cant work this out. I try looping through the interest variable with for loop but this doesn't work either.
var interest = GetValue2(tvp, connectionString); -- this is my method that returns a string
textBox2.Text = string.Join(", ", interest.ToString());
this returns "System.Collections.Generic.List`1[System.String]" to textbox2. Any ideas what im missing here? thanks
PART 2:
public static List<String> GetValue2(DataTable tvp, String connectionString)
{
List<String> items = new List<String>();
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("[dbo].[...]", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParameter = new SqlParameter();
tvpParameter.ParameterName = "#..";
tvpParameter.SqlDbType = System.Data.SqlDbType.Structured;
tvpParameter.Value = tvp;
tvpParameter.TypeName = "[dbo].[....]";
cmd.Parameters.Add(tvpParameter);
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine((String)rdr["id"]);
}
Console.ReadLine();
}
}
return items;
}
Could you share the GetValue2 method? Probably you are calling ToString() on List in that method and it that case the GetValue2 method returns
"System.Collections.Generic.List1[System.String]"
Example:
var test = new List<string>{"some text"};
test.ToString(); // returns System.Collections.Generic.List`1[System.String]
Update:
Because the method GetValue2 returns List<string> avoid calling .ToString() on interest
var interest = GetValue2(tvp, connectionString); // returns List<string>
textBox2.Text = string.Join(", ", interest);
There's also the issue of the List<string> items inside the GetValue2() not being populated.
Here's the corrected method:
public static List<String> GetValue2(DataTable tvp, String connectionString)
{
List<String> items = new List<String>();
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("[dbo].[...]", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParameter = new SqlParameter();
tvpParameter.ParameterName = "#..";
tvpParameter.SqlDbType = System.Data.SqlDbType.Structured;
tvpParameter.Value = tvp;
tvpParameter.TypeName = "[dbo].[....]";
cmd.Parameters.Add(tvpParameter);
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
items.Add((String)rdr["id"]);
}
}
}
return items;
}
In my main form, I have implemented this code..
void SampleMethod(string name, string lastName, string database)
{
SqlParameter sqlParam = new SqlParameter();
sqlParam.ParameterName = "#name";
sqlParam.Value = name;
sqlParam.SqlDbType = SqlDbType.NVarChar;
SqlParameter sqlParam1 = new SqlParameter();
sqlParam1.ParameterName = "#lastName";
sqlParam1.Value = lastName;
sqlParam1.SqlDbType = SqlDbType.NVarChar;
SqlParameter sqlParam2 = new SqlParameter();
sqlParam2.ParameterName = "#database";
sqlParam2.Value = database;
sqlParam2.SqlDbType = SqlDbType.NVarChar;
SampleClass sampleClass = new SampleClass(new DBConn(#serverName, tableName, userName, password));
sampleClass.executeStoredProc(dataGridView1, "sp_sampleStoredProc", sqlParam, sqlParam1, sqlParam2);
}
And in my SampleClass, I have this kind of method.
public DataGridView executeStoredProc(DataGridView dtgrdView, string storedProcName, params SqlParameter[] parameters)
{
try
{
DataTable dt = new DataTable();
sqlDA = new SqlDataAdapter(storedProcName, sqlconn);
sqlDA.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlDA.SelectCommand.CommandTimeout = 60;
// Loop through passed parameters
if (parameters != null && parameters.Length > 0)
{
foreach (var p in parameters)
sqlDA.SelectCommand.Parameters.Add(p);
}
sqlDA.Fill(dt);
dtgrdView.DataSource = dt;
sqlconn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
sqlconn.Close();
}
return dtgrdView;
}
What I am trying to do is avoid multiple
SqlParameter sqlParam = new SqlParameter()
in my code, I have tried so many solutions for this problem but I didn't get the right answer. I have also tried to research about this but I still couldn't get the right answer.
Please don't mind my naming convention and other codes as I intentionally change many of them :) Thanks.
As an alternative to your solution, try to use already existing one instead, using Dapper (https://github.com/StackExchange/dapper-dot-net).
You still need to use multiple parameters if your stored procedure or query needs it, but this is nicely abstracted for you and this will definatelly reduce the amount of code.
void SampleMethod(string name, string lastName, string database)
{
using(var connection = new SqlConnection(MY_CONNECTION_STRING))
{
var resultListOfRows = connection.Query<ReturnObject>(MY_STORED_PROCEDURE, new {
name = name,
lastName = lastName,
database = database}, commandType: System.Data.CommandType.StoredProcedure);
}
}
First of all, the easiest option would be to use a microORM like Dapper, and retrieve a strongly-typed collection. Gridviews can bind to anything, including strongly typed collections. All this code could become:
using(var con=new SqlConnection(myConnectionString))
{
con.Open();
var result= connection.Query<ResultClass>("sp_MySproc",
new { Name= name, LastName= lastName,Database=database},
commandType: CommandType.StoredProcedure);
return result;
}
Even when using raw ADO.NET, you can create a SqlParameter in one line by using the appropriate constructor . For example, you can create a new nvarchar(n) parameter with:
var myParam=new SqlParameter("#name",SqlDbType.NVarchar,20);
or
var myParam=new SqlParameter("#name",SqlDbType.NVarchar,20){Value = name};
A better idea though is to create the SqlCommand object just once and reuse it. Once you have an initialized SqlCommand object, you can simply set a new connection to it and change the parameter values, eg:
public void Init()
{
_loadCustomers = new SqlCommand(...);
_loadCustomers.Parameters.Add("#name",SqlDbType.NVarChar,20);
...
}
//In another method :
using(var con=new SqlConnection(myConnectionString)
{
_loadCustomers.Connection=con;
_loadCustomers.Parameters["#name"].Value = myNameParam;
con.Open();
using(var reader=_load.ExecuteReader())
{
//...
}
}
You can do the same thing with a SqlDataAdapter, in fact that's how Windows Forms and Data Adapters are meant to be used since .NET 1.0 .
Instead of creating a new one each time you want to fill your grid, create a single one and reuse it by setting the connection and parameters before execution. You can use the SqlDataAdapter(SqlCommand) constructor to make things a bit cleaner:
public void Init()
{
_loadCustomers = new SqlCommand(...);
_loadCustomers.Parameters.Add("#name",SqlDbType.NVarChar,20);
....
_myGridAdapter = new SqlDataAdapter(_loadCustomers);
...
}
And call it like this:
using(var con=new SqlConnection(myConnectionString))
{
_myGridAdapter.SelectCommand.Connection=con;
_myGridAdapter.SelectCommand.Parameters["#name"].Value =....;
con.Open();
var dt = new DataTable();
_myGridAdapter.Fill(dt);
dtgrdView.DataSource = dt;
return dtgrdView;
}
Separate your Database logic at one place(put sqladapter, sqlcommand etc at one place), Then encapsulate parameters within your command like mentioned below and you don't need to declare sqlparameter separately, add it inside parameters list.
cmdToExecute.Parameters.Add(new SqlParameter("#parameter", value));
Take a look at the complete example below
public DataTable ProdTypeSelectAll(string cultureCode)
{
SqlCommand cmdToExecute = new SqlCommand();
cmdToExecute.CommandText = "dbo.[pk_ProdType_SelectAll]";
cmdToExecute.CommandType = CommandType.StoredProcedure;
DataTable toReturn = new DataTable("ProdType");
SqlDataAdapter adapter = new SqlDataAdapter(cmdToExecute);
cmdToExecute.Connection = _mainConnection;
cmdToExecute.Parameters.Add(new SqlParameter("#CultureName", cultureCode));
_mainConnection.Open();
adapter.Fill(toReturn);
return toReturn;
}
You may be able to use the SqlParameter Constructor (String, Object). Replace:
sampleClass.executeStoredProc(dataGridView1,
"sp_sampleStoredProc",
sqlParam,
sqlParam1,
sqlParam2);
With:
sampleClass.executeStoredProc(dataGridView1,
"sp_sampleStoredProc",
new SqlParameter("#name", (object)name),
new SqlParameter("#lastName", (object)lastName),
new SqlParameter("#database", (object)database));
I am creating a method that can be called from anywhere in my application that will take in the named of a stored procedure and a list of parameters to pass to it.
In doing this I ran across the Parameters.AddWithValue command, but also ran across a blog posts and some SO posts that say this is bad due to conversion issues. They all recommended to add parameters using
Parameters.Add(PARAMETER, SqlDbType.TYPE);
but the problem with this is if I have a method like mine how do I properly use the Parameters.Add method when I don't know what type the parameters are when they come in? What is a good way to address this, or am I being overly paranoid and just should stick with Parameters.AddWithValue?
For reference here is the base method right now that I am attempting to update so it can handle parameters
public static DataTable ExecuteDynamicsStoredProc(string procedureName)
{
var dataTable = new DataTable();
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DynamicsDB"].ToString()))
{
using (var command = new SqlCommand("c2s_ProjectPerformanceReport", connection))
{
connection.Open();
command.CommandType = CommandType.StoredProcedure;
var dataAdapter = new SqlDataAdapter();
dataAdapter.SelectCommand = command;
dataAdapter.Fill(dataTable);
return dataTable;
}
}
}
You can make the method accept a SqlParameter[] and use command.Parameters.AddRange().
public static DataTable ExecuteDynamicsStoredProc(string procedureName, SqlParameter[] args) {
var dataTable = new DataTable();
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DynamicsDB"].ToString())) {
using (var command = new SqlCommand(procedureName, connection)) { //use passed in proc name
connection.Open();
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddRange(args); //add all the parameters
var dataAdapter = new SqlDataAdapter();
dataAdapter.SelectCommand = command;
dataAdapter.Fill(dataTable);
return dataTable;
}
}
}
public static void ExecuteProcOne(string name, int age, bool alive) {
SqlParameter p1 = new SqlParameter("name", name);
SqlParameter p2 = new SqlParameter("age", age);
SqlParameter p3 = new SqlParameter("alive", alive);
var result = ExecuteDynamicsStoredProc("ExecuteProcOne", new SqlParameter[] { p1, p2, p3 });
}
Use methods like ExecuteProcOne() to handle the individual procedures with their respective datatypes. You can extract this out further to make a method return the SqlParameter[].
This way you can just call MyProcName and you know what parameters you need from intellisense.
So I wish to create a nice function that will query MySQL commands in a nicer way. Something along the lines of this one:
public int mysql_query_scalar(string query, parameters)
{
mysql_Open();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = mysql_connection;
cmd.CommandText = query;
cmd.Prepare();
cmd.Parameters.AddWithValue(parameterfromstring, parameternumber);
mysql_Close();
return int.Parse(cmd.ExecuteScalar().ToString());
}
Now, what I wish to do is to be able to add as many parameters as I can, and then start building up parameters. How is this possible? If so, please tell me or give me a snippet of it please.
I will gladly appreciate someone telling me how to use it too. I am pretty new to MySQL and I am not C# expert.
mysql_Open(); and mysql_Close(); are functions I did myself. Refer them as mysql_connection.Open(); and mysql_connection.Close();
You can use an extension method, like this:
public static class DbCommandExtensions
{
public static void AddInputParameters<T>(this IDbCommand cmd,
T parameters) where T : class
{
foreach (var prop in parameters.GetType().GetProperties())
{
object val = prop.GetValue(parameters, null);
var p = cmd.CreateParameter();
p.ParameterName = prop.Name;
p.Value = val ?? DBNull.Value;
cmd.Parameters.Add(p);
}
}
}
Call as below :
cmd.AddInputParameters(new { a = textBox1.Text, b = TextBox2.Text.... });
i would call this method that way:
List<SqlParameter> sList = new List<SqlParameter>();
sList.Add(new SqlParameter("#myValue", myValue));
sList.Add(new SqlParameter("#myValue2", myValue2));
mysql_query_scalar(myQuery, sList.ToArray());
and i would use using-directives
public static int mysql_query_scalar(string Command, SqlParameter[] parameters)
{
using (MySqlConnection myConnection = new MySqlConnection(ConnectionString))
{
myConnection.Open();
using (MySqlCommand myCommand = new MySqlCommand(Command, myConnection))
{
myCommand.Parameters.AddRange(parameters); // Add Parameters here
return (int)myCommand.ExecuteScalar();
}
}
}
I have a Command object like this:
SqlCommand cmd1 = new SqlCommand();
How can I build the sqlParameterCollection in another routine and pass this collection to this Command object?
I have this code:
private SqlParameterCollection BuildParameters()
{
SqlCommand cmd2 = new SqlCommand();
cmd2.Parameters.Add("#year", SqlDbType.Int).Value = 2013;
return cmd2.Parameters;
}
I would like to do something like this:
cmd1.Parameters = BuildParameters();
The SqlCommand.Parameters property is read only so you cannot assign an SqlParameterCollection object to it.
You may want to return an SqlParameter array from BuildParameters thus:
private SqlParameter[] BuildParameters()
{
SqlParameter[] para = new SqlParameter[3];
para[0] = new SqlParameter("#year", SqlDbType.Int) { Value = 2013 };
return para;
}
Then you can do the following:-
SqlCommand cmd1 = new SqlCommand();
cmd1.Parameters.Clear();
cmd1.Parameters.AddRange(BuildParameters());
you could handle this as an extension method, but honestly I don't know really how useful this would be
public static IEnumerable<IDbDataParameter> BuildParameters(this IDbCommand command, params KeyValuePair<string, DbType>[] parameters)
{
foreach(KeyValuePair<string, DbType> kvpParam in parameters)
{
IDbDataParameter param = command.CreateParameter();
param.ParameterName = kvpParam.Key;
param.DbType = kvpParam.Value;
yield return param;
}
}
You can simple iterate throught the collection.
foreach (var mysqlParamater in oMySqlParameterCollection)
{
oMySqlCommand.Parameters.Add(mysqlParamater);
}
I have written a method that accept mysqlparamater collection along with SP name you can use it as below:-
public int ExecuteNonQuery(MySqlParameterCollection oMySqlParameterCollection, string storedProcedure)
{
int affectedRows = 0;
_oMySqlConnection.Open();
MySqlCommand oMySqlCommand = new MySqlCommand
{
CommandType = CommandType.StoredProcedure,
CommandText = storedProcedure,
Connection = _oMySqlConnection
};
foreach (var mysqlParamater in oMySqlParameterCollection)
{
oMySqlCommand.Parameters.Add(mysqlParamater);
}
affectedRows = oMySqlCommand.ExecuteNonQuery();
_oMySqlConnection.Close();
return affectedRows;
}