Sqlparameters - pass them to a method - c#

I have a method like this one:
private void SetDataSet(string sqlString, params SqlParameter[] parameters)
{
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
//cmd.CommandType = CommandType.
cmd.CommandText = sqlString;
if (parameters != null)
{
foreach (SqlParameter parm in parameters)
{
cmd.Parameters.Add(parm);
}
}
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
cmd.ExecuteScalar();
}
}
}
}
Now, from the other method called testMethod, I'd like to call "SetDataSet" with all needed arguments. Unfortunately I don't know how to "construct" the needed sqlparameters and how, later, pass them info "SetDataSet" method.
private void testMethod()
{
string sqlString = .... .
//here should be the code, which will create sql parameters
//and now we call the SetDataSet with all needed arguments:
SetDataSet(sqlString, ?!);
}
I was thinking about some kind of loop, which could create sqlparameters array(?) in testMethod, and then pass it to the SetDataSet method, however dont know how to accomply that.
Any thoughts?

You need to create SQL parameters?
Like this:
SqlParameter SqlParm = new SqlParameter("ID", SqlDbType.Int);
SqlParm.Value = 100;
If you think you are making some kind of generic way to do all your database stuff, you will end up creating a new layer but not avoiding the nuts and bolts of accessing a database.

All you have to do is provide the parameters. The params parameter will automatically create the array.
SetDataSet(sqlString, param1, param2, param3, ..., paramN);

You need to create SQL parameters?
Like this:
SqlParameter sqlP1= new SqlParameter("Id", SqlDbType.Int);
sqlP1.Value = 200;

So what you are trying to do is something like this:
private void testMethod()
{
string sqlString = .....
//here should be the code, which will create sql parameters
// An varchar(80) parameter called #Name with the value "Chuck".
SqlParameter paramName = new SqlParameter("#Name", SqlDbType.VarChar, 80);
paramName.Value = "Chuck";
// An int parameter called #Age with the value 49.
SqlParameter paramAge = new SqlParameter("#Age", SqlDbType.Int);
paramAge.Value = 49;
// Create more parameters here, as many as you want.
// You could also create a SqlParameter[] array and send in instead.
//and now we call the SetDataSet with all needed arguments:
SetDataSet(sqlString, paramName, paramAge); // just add all parameters one after another.
}
Since you are using a params parameter in SetDataSet(string sqlString, params SqlParameter[] parameters) you can add zero or how many parameters you want after the sqlString parameter.

Related

C# SQL Command parameter not working

I've done some trouble shooting by taking out the parameters and replacing them with text, and the only parameter that is not working is #seat and I can't figure out why.
allSeats is an array of custom controls. I've tried replacing the parameter contents with an actual string ie. "A1" and that still doesn't work. If I remove the #seat parameter and replace it with A1, it works, but I need to be able to set the column name dynamically.
myConnection.Open();
SqlCommand myCommand = new SqlCommand("UPDATE Events SET #seat = #truefalse WHERE Name = #name", myConnection);
SqlParameter param = new SqlParameter();
SqlParameter param2 = new SqlParameter();
SqlParameter param3 = new SqlParameter();
param.ParameterName = "#seat";
param2.ParameterName = "#truefalse";
param2.DbType = System.Data.DbType.Boolean;
param3.ParameterName = "#name";
param.Value = allSeats[i].Name;
param2.Value = allSeats[i].taken;
param3.Value = name;
myCommand.Parameters.Add(param);
myCommand.Parameters.Add(param2);
myCommand.Parameters.Add(param3);
myCommand.ExecuteNonQuery();
Any help is appreciated. If I need to post more relevant code please let me know and I shall add it.
In your
SET #seat = #truefalse
part, you try to parameterize your column name. You can't do that. You only can parameterize your values, not column name or table names.
You can use dynamic SQL for such a case but it is not recommended. Read
The Curse and Blessings of Dynamic SQL
SELECT * FROM #tablename
As a recommendation, use a white list such a case. I hope, there can only be a fixed set of possible correct values for the column name. Of course, this requires strong validation in your inputs part.
Agree with Soner. Change the string before you create the command
string cmdStr = string.Format("UPDATE Events SET {0} = #truefalse WHERE Name = #name", allSeats[i].Name)
Then
only use 2 parameters.
SqlCommand myCommand = new SqlCommand(cmdStr, myConnection);
SqlParameter param = new SqlParameter();
SqlParameter param2 = new SqlParameter();
etc.
cmd.parameter.addwithvalue("#param1", value1);
cmd.parameter.addwithvalue("#param2", value2);
use like this.
As Soner has mentioned, columns cannot be parameterized. This means you will either have to create dynamic queries, or create all the parameterized once at the startup, one query per column name.
this can be done in the following example:
private static Dictionary<string, SqlCommand> parameterizedCommands = new Dictionary<string,SqlCommand>();
public static void CreateparameterizedCommandsy(string[] colums)
{
parameterizedCommands = new Dictionary<string,SqlCommand>();
foreach (string colname in colums)
{
parameterizedCommands.Add(colname, CreateCommandForColumn(colname));
}
}
public static SqlCommand CreateCommandForColumn(string columnName)
{
SqlCommand myCommand = new SqlCommand(string.Format("UPDATE Events SET {0} = #truefalse WHERE Name = #name",columnName));
// the following statement creates the parameter in one go. Bit = boolean
myCommand.Parameters.Add("#truefalse", SqlDbType.Bit);
myCommand.Parameters.Add("#name", SqlDbType.Text);
return myCommand;
}
public int ExccuteColumnUpdate(string columnName, bool setToValue, string name, SqlConnection connection)
{
connection.Open();
try
{
SqlCommand command;
if (parameterizedCommands.TryGetValue(columnName, out command))
{
command.Connection = connection;
command.Parameters["#truefalse"].Value = setToValue;
command.Parameters["#name"].Value = name;
return command.ExecuteNonQuery();
}
}
finally
{
connection.Close();
}
return 0;
}

Generic Sybase stored procedure execution in C#

I'd like to execute Sybase stored procedure the same way I am doing in a SQL IDE, i.e. something like this in SQL:
exec sp_GetCMyDataPerRegion JAPAN'
However, instead of this, in the C# code I am forced to define each parameter individually, each having all those types defined:
AseCommand command = new AseCommand(spName, DbConnection);
command.CommandType = CommandType.StoredProcedure;
AseParameter param = command.CreateParameter();
param.ParameterName = "#region";
param.AseDbType = AseDbType.VarChar;
param.Direction = ParameterDirection.Input;
param.Value = myValue;
command.Parameters.Add(param);
Quite a pain and not finding anyway so far to have it "generic", i.e. would just like to wrap the store procedure call in a method with this kind of signature:
public AseDataReader ExecuteStoredProcedure(string spExecutionString){}
Would you have any way on doing so?
Thank you in advance!
I do have an example of an SqlDataReader where the Function call is
ExecuteNonQuery("dbo.[Sp_Skp_UpdateFuncties]", parameters);
This is in a class DataBaseManager which hold the databaseconnectionstring
public classDataBaseManager
{
...
public int ExecuteStoredProcedure(string storedprocedureNaam, IEnumerable<KeyValuePair<string, object>> parameters)
{
var sqlCommand = new SqlCommand
{
Connection = DatabaseConnectie.SqlConnection,
CommandType = CommandType.StoredProcedure,
CommandText = storedprocedureNaam,
};
foreach (KeyValuePair<string, object> keyValuePair in parameters)
{
sqlCommand.Parameters.Add(
new SqlParameter { ParameterName = "#" + keyValuePair.Key, Value = keyValuePair.Value ?? DBNull.Value }
);
}
if (sqlCommand == null)
throw new KoppelingException("Stored procedure ({0}) aanroepen lukt niet", storedprocedureNaam);
return sqlCommand.ExecuteNonQuery();
}
....
}

How do I add parameters to the following stored procedure call?

How do I add parameters to the following stored procedure call?
using (var conn = new SqlConnection(connectionString))
using (var command = new SqlCommand("ProcedureName", conn) {
CommandType = CommandType.StoredProcedure }) {
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
Like this:
// this would work for a varchar or nvarchar parameter
command.Parameters.AddWithValue("#yourParameter", "someValue");
// this would work for an integer parameter
command.Parameters.AddWithValue("#someInt", 1234);
Obviously you need any code to add parameters to the Parameters collection before you try to call command.ExecuteNonQuery();.
You can use command.Parameters.AddWithValue("#number", TextBox1.Text)
Happy coding!!
I thing you need to be more specific.
What is the problem with using command.Parameters.AddWithValue ?
command.Parameters.Add(
new SqlParameter("#customerId", custumerId));
This might be a solution:
This parameter should be the exact name of the parameter from your stored procedure("yourParameter").
using (var conn = new SqlConnection(connectionString))
{
var command = new SqlCommand("ProcedureName", conn){CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("#yourParameter", "someValue");
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
You can use SqlCommand.Parameters Property.
command.Parameters.Add("#SomeParmeter", SqlDbType.Int); //SqlDbType is enum
For more details go thru this link : http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx
below code is copied from the above posted link
static void GetSalesByCategory(string connectionString,string categoryName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create the command and set its properties.
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "SalesByCategory";
command.CommandType = CommandType.StoredProcedure;
// Add the input parameter and set its properties.
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#CategoryName";
parameter.SqlDbType = SqlDbType.NVarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = categoryName;
// Add the parameter to the Parameters collection.
command.Parameters.Add(parameter);
// Open the connection and execute the reader.
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}: {1:C}", reader[0], reader[1]);
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
}
}

How to pass a table-value parameter

I am trying to pass a table-value parameter to a stored procedure, but I keep getting an exception (see below).
SqlCommand c = new SqlCommand("getPermittedUsers", myConn) { CommandType = CommandType.StoredProcedure };
c.Parameters.AddWithValue("#intNotifyingUserId", notifyingUserId);
c.Parameters.AddWithValue("#tSelectedPdfIds", sharedPdfs).SqlDbType = SqlDbType.Structured;
SqlDataReader dr = c.ExecuteReader();
The type is defined on the server like this:
CREATE TYPE [dbo].[IdList] AS TABLE(
[Id] [int] NOT NULL
)
I have tried passing sharedPdfs as a List<int>, and IQueryable<int>, but keep getting the following exception:
Object must implement IConvertible.
Anyone know what I am doing wrong? The documentation implies that I should be able to pass a list as a TVP but doesn't give any examples.
Thank you.
The following example illustrates using either a DataTable or an IEnumerable<SqlDataRecord>:
SQL Code
CREATE TABLE dbo.PageView
(
PageViewID BIGINT NOT NULL CONSTRAINT pkPageView PRIMARY KEY CLUSTERED,
PageViewCount BIGINT NOT NULL
);
CREATE TYPE dbo.PageViewTableType AS TABLE
(
PageViewID BIGINT NOT NULL
);
CREATE PROCEDURE dbo.procMergePageView
#Display dbo.PageViewTableType READONLY
AS
BEGIN
MERGE INTO dbo.PageView AS T
USING #Display AS S
ON T.PageViewID = S.PageViewID
WHEN MATCHED THEN UPDATE SET T.PageViewCount = T.PageViewCount + 1
WHEN NOT MATCHED THEN INSERT VALUES(S.PageViewID, 1);
END
C# Code
private static void ExecuteProcedure(bool useDataTable, string connectionString, IEnumerable<long> ids) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = "dbo.procMergePageView";
command.CommandType = CommandType.StoredProcedure;
SqlParameter parameter;
if (useDataTable) {
parameter = command.Parameters.AddWithValue("#Display", CreateDataTable(ids));
}
else {
parameter = command.Parameters.AddWithValue("#Display", CreateSqlDataRecords(ids));
}
parameter.SqlDbType = SqlDbType.Structured;
parameter.TypeName = "dbo.PageViewTableType";
command.ExecuteNonQuery();
}
}
}
private static DataTable CreateDataTable(IEnumerable<long> ids) {
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(long));
foreach (long id in ids) {
table.Rows.Add(id);
}
return table;
}
private static IEnumerable<SqlDataRecord> CreateSqlDataRecords(IEnumerable<long> ids) {
SqlMetaData[] metaData = new SqlMetaData[1];
metaData[0] = new SqlMetaData("ID", SqlDbType.BigInt);
SqlDataRecord record = new SqlDataRecord(metaData);
foreach (long id in ids) {
record.SetInt64(0, id);
yield return record;
}
}
You can pass the parameter as a DataTable, IEnumerable<SqlDataRecord>, or DbDataReader.
Adding a new answer with updated links.
According to the documentation (learn.microsoft.com), you can use one of the following parameter types:
SqlClient supports populating table-valued parameters from DataTable, DbDataReader or IEnumerable \ SqlDataRecord objects. You must specify a type name for the table-valued parameter by using the TypeName property of a SqlParameter. The TypeName must match the name of a compatible type previously created on the server.
Not included in the docs but important for high-performance apps, a sample using IEnumerable<SqlDataRecord> (.NET Core 3.1, async):
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));
using SqlConnection connection = this.GetConnection();
await connection.OpenAsync(timeout.Token);
using SqlCommand command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "Mycommand";
IEnumerable<SqlDataRecord> records = // ...
SqlParameter parameter = command.Parameters.Add("#MyObjects", SqlDbType.Structured);
parameter.TypeName = "MyCustomTableType";
parameter.Value = records;
await command.ExecuteNonQueryAsync(timeout.Token);
Example using a DataTable:
// Create a DataTable with the modified rows.
DataTable addedCategories = CategoriesDataTable.GetChanges(DataRowState.Added);
// Configure the SqlCommand and SqlParameter.
SqlCommand insertCommand = new SqlCommand("usp_InsertCategories", connection);
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue("#tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;
// Execute the command.
insertCommand.ExecuteNonQuery();
Example using DbDataReader:
// Assumes connection is an open SqlConnection.
// Retrieve data from Oracle.
OracleCommand selectCommand = new OracleCommand(
"Select CategoryID, CategoryName FROM Categories;",
oracleConnection);
OracleDataReader oracleReader = selectCommand.ExecuteReader(
CommandBehavior.CloseConnection);
// Configure the SqlCommand and table-valued parameter.
SqlCommand insertCommand = new SqlCommand(
"usp_InsertCategories", connection);
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam =
insertCommand.Parameters.AddWithValue(
"#tvpNewCategories", oracleReader);
tvpParam.SqlDbType = SqlDbType.Structured;
// Execute the command.
insertCommand.ExecuteNonQuery();

How to add a number to a Sqlcommand.Parameters?

Here's my method:
public void EjecutarGuardar(string ProcedimientoAlmacenado, object[] Parametros)
{
SqlConnection Connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand Command = Connection.CreateCommand();
Command.CommandText = ProcedimientoAlmacenado;
Command.CommandType = CommandType.StoredProcedure;
foreach (object X in Parametros)
{
Command.Parameters.Add(X);
}
Connection.Open();
Command.ExecuteNonQuery();
Connection.Close();
Connection.Dispose();
}
Say I added an int to my object array PARAMETROS, when it reaches the foreach statement I get an error:
The SqlParameterCollection only
accepts non-null SqlParameter type
objects, not Int32 objects.
So, how can I load all of my parameters outside of this class, and then place them all into a generic array, and pass it on to this method to do it's magic. Any help?
Edit: A friend sent me this code, would it work? I cant understand what it's doing. :S
protected void CargarParametros(SqlCommand Com, System.Object[] Args)
{
for (int i = 1; i < Com.Parameters.Count; i++)
{
SqlParameter P = (SqlParameter)Com.Parameters[i];
if (i <= Args.Length )
P.Value = Args[i - 1];
else
P.Value = null;
}
}
Use AddWithValue method,
string []para={"#eno","#ename","#edate"};
object []val={11,"A","1-1-2002"};
System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(#"");
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.CommandText = "proc_name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = cn;
for(int i=0;i<para.Length;i++){
cmd.Parameters.AddWithValue(para[i], val[i]);
}
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
Your SqlCommand wraps up the stored procedure. In order to call it, you will need to create an instance of a SqlParameter for each parameter that you pass into or get out of the stored procedure. You cannot just simply add your values - how would ADO.NET know which value to assign to which parameter??
Each SqlParameter contains things like:
a name
its datatype
possibly restrictions (on size, length)
and possibly a value
So in your case, your statement should look something like this:
SqlCommand Command = Connection.CreateCommand();
Command.CommandText = ProcedimientoAlmacenado;
Command.CommandType = CommandType.StoredProcedure;
foreach (object X in Parametros)
{
SqlParameter param = new SqlParameter();
param.ParameterName = Parametros.Name;
// you need to find a way to determine what DATATYPE the
// parameter will hold - Int, VarChar etc.
param.SqlDbType = SqlDbType.Int;
param.Value = Parametros.Value;
Command.Parameters.Add(param);
}
So, just adding values isn't going to work - you need to capture those parameters with their name, data type, length etc. and their values.
Marc
You need to do this:
Sql command example:
"SELECT * FROM YourTable WHERE FirstColumn = #YourParameterID;"
To add a parameter for this command:
Command.Parameters.Add(new SqlParameter("#YourParameterID", SqlDbType.Int).Value = X);
I'm not an expert, but I guess you should name your parameters; so instead of just having an array of object, you should consider having an array of key-value pairs.
Then, you should take a look at one of SqlParameter constructors: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.sqlparameter.aspx
You can also use an abbreviated version. ADO.NET will know it's a number and will insert the proper datatype if you do this:
Command.Parameters.Add(new SqlParameter("#YourParameterID", 4));
etc.
Also, make sure you're not inserting a NULL into a NOT NULL data field, and is implicitly castable to type SqlParameter.

Categories

Resources