This is a basic c# application but I am quite rusty. I am just going to start with showing you my code
using System;
using System.Data.SqlClient;
using System.Text;
namespace DatabaseAdder
{
class Program
{
static void Main(string[] args)
{
int RUId = 0;
int QuestionId = 0;
DateTime Date = DateTime.Now;
string QuestionWhenAnswered ;
string QuestionResponse;
int Accepted;
string AssignedWorkStation;
string CompleteToken;
try
{for (int i = 0; i < 300; i++) {
QuestionId ++;
QuestionIncrementInSetsOfTwelve(QuestionId);
Console.WriteLine(i );
Console.WriteLine( QuestionId);
Random rand = new Random();
// Build connection string
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "localhost"; // update me
builder.UserID = "sa"; // update me
builder.Password = "Mypassword123"; // update me
builder.InitialCatalog = "CDA";
// Connect to SQL
Console.Write("Connecting to SQL Server ... ");
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
var sql = "INSERT INTO QuestionResponses(RUId, QuestionId,Date,QuestionWhenAnswered,QuestionResponse,Accepted,AssignedWorkStation,CompleteToken)" +
" VALUES(#RUId, #QuestionId,#Date,#QuestionWhenAnswered,#QuestionResponse,#Accepted,#AssignedWorkStation,#CompleteToken)";
using (var cmd = new SqlCommand(sql, connection))
{
cmd.Parameters.AddWithValue("#RUId", "1" );
cmd.Parameters.AddWithValue("#QuestionId", "1");
cmd.Parameters.AddWithValue("#Date", DateTime.Now);
cmd.Parameters.AddWithValue("#QuestionWhenAnswered", "sam");
cmd.Parameters.AddWithValue("#QuestionResponse", "sam");
cmd.Parameters.AddWithValue("#Accepted", "1");
cmd.Parameters.AddWithValue("#AssignedWorkStation", "sam");
cmd.Parameters.AddWithValue("#CompleteToken", "sam");
cmd.ExecuteNonQuery();
}
}
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("All done. Press any key to finish...");
Console.ReadKey(true);
}
static int QuestionIncrementInSetsOfTwelve(int questionId)
{
if(questionId < 12)
{
questionId = 0;
}
else
{
}
return questionId;
}
}
}
The questionincrementinsetsoftwelve is not changing the value when it is called even when I have debugged and can watch that its value is over 12 but it is still not setting this back to 0.
I understand that there is probably something very small I am overlooking so be easy on my ego.
This bit
QuestionId ++;
QuestionIncrementInSetsOfTwelve(QuestionId);
Should be
QuestionId ++;
QuestionId = QuestionIncrementInSetsOfTwelve(QuestionId);
integers are passed by value, not by reference. So a new integer that has the same value as QuestionId is being passed to the method, and that new integer is being returned from it. You have to assign the result. The behavior you are looking for can be achieved by using the ref keyword but isn't needed so long as we assign the result.
You're passing QuestionIncrementInSetsOfTwelve() a value. It's not updating the parameter, it's taking it in, doing "stuff," and returning a new value.
If you want to alter the parameter passed in, use the ref keyword.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
Example from microsoft:
void Method(ref int refArgument)
{
refArgument = refArgument + 44;
}
int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45
Notice how this returns nothing? It updates the argument passed in, because it was passed by ref.
Related
I'm using C# to extract data to T-SQL parameters, the query is:
DECLARE #Param1 INT, #Param2 NCHAR(50), #P3 REAL, #P4 BIT
SELECT #Param1 = [idx]
,#Param2 = [data]
,#P3 = [itgetsreal]
,#P4 = [wazzup]
FROM [T].[dbo].[temp];
Running from MS SQL Server Management Studio yields a predictable one line dataset, the last. My C# code creates output parameters:
public class ParamData
{ // query has executed, return parameter data in class properties
public string[] names; public Object[] vals; public bool success = false;
public ParamData(SqlCommand cmd)
{
if (cmd == null) {
err = "SqlCommand \"cmd\" may not be NULL";
errcode = -1; errdata = ""; errsrc = "ParamData(SqlCommand cmd)"; }
else {
if (cmd.Parameters == null) { err = "\"SqlCommand.Parameters\" may not be NULL";
errcode = -1; errdata = cmd.CommandText; errsrc = "ParamData(SqlCommand cmd)"; }
else {
try {err = ""; errcode = 0; errdata = ""; errsrc = "";
int cnt = cmd.Parameters.Count;
if (cnt > 0) {
names = new string[cnt]; vals = new object[cnt];
for (int i = 0; i < cnt; i++)
{
names[i] = cmd.Parameters[i].ParameterName;
vals[i] = cmd.Parameters[i].Value;
}
}
success = true;
}
catch (SqlException ex) {
err = ex.Message; errcode = ex.Number;
errdata = String.Format("Parameters name/val assignment: Query: \"{0}\"",
cmd.CommandText);
errsrc = "ParamData(SqlCommand cmd)";}
}
}
}
}
How do I create a SqlReader type object where I can extract each row of the dataset and not only the last?
BTW: I've got means already to bring in the data without parameters but am constrained to provide a legacy compatibility and can't yet replicate the original function.
You can't return multiple rows of T-SQL variables/parameters. Parameters only hold the last value.
The comments are spot on - one needs to return datasets (not through parameters) to obtain multiple rows.
I am using MySQLClient with a local database. I wrote a method which returns a list of data about the user, where I specify the columns I want the data from and it generates the query dynamically.
However, the reader is only returning the column names rather than the actual data and I don't know why, since the same method works previously in the program when the user is logging in.
I am using parameterised queries to protect from SQL injection.
Here is my code. I have removed parts which are unrelated to the problem, but i can give full code if needed.
namespace Library_application
{
class MainProgram
{
public static Int32 user_id;
static void Main()
{
MySqlConnection conn = LoginProgram.Start();
//this is the login process and works perfectly fine so i won't show its code
if (conn != null)
{
//this is where things start to break
NewUser(conn);
}
Console.ReadLine();
}
static void NewUser(MySqlConnection conn)
{
//three types of users, currently only using student
string query = "SELECT user_role FROM Users WHERE user_id=#user_id";
Dictionary<string, string> vars = new Dictionary<string, string>
{
["#user_id"] = user_id.ToString()
};
MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
if (reader.Read())
{
string user_role = reader["user_role"].ToString();
reader.Close();
//this works fine and it correctly identifies the role and creates a student
Student user = new Student(conn, user_id);
//later i will add the logic to detect and create the other users but i just need this to work first
}
else
{
throw new Exception($"no user_role for user_id - {user_id}");
}
}
}
class SQLControler
{
public static MySqlDataReader SqlQuery(MySqlConnection conn, string query, Dictionary<string, string> vars, int type)
{
MySqlCommand cmd = new MySqlCommand(query, conn);
int count = vars.Count();
MySqlParameter[] param = new MySqlParameter[count];
//adds the parameters to the command
for (int i = 0; i < count; i++)
{
string key = vars.ElementAt(i).Key;
param[i] = new MySqlParameter(key, vars[key]);
cmd.Parameters.Add(param[i]);
}
//runs this one
if (type == 0)
{
Console.WriteLine("------------------------------------");
return cmd.ExecuteReader();
//returns the reader so i can get the data later and keep this reusable
}
else if (type == 1)
{
cmd.ExecuteNonQuery();
return null;
}
else
{
throw new Exception("incorrect type value");
}
}
}
class User
{
public List<string> GetValues(MySqlConnection conn, List<string> vals, int user_id)
{
Dictionary<string, string> vars = new Dictionary<string, string> { };
//------------------------------------------------------------------------------------
//this section is generating the query and parameters
//using parameters to protect against sql injection, i know that it ins't essential in this scenario
//but it will be later, so if i fix it by simply removing the parameterisation then im just kicking the problem down the road
string args = "";
for (int i = 0; i < vals.Count(); i++)
{
args = args + "#" + vals[i];
vars.Add("#" + vals[i], vals[i]);
if ((i + 1) != vals.Count())
{
args = args + ", ";
}
}
string query = "SELECT " + args + " FROM Users WHERE user_id = #user_id";
Console.WriteLine(query);
vars.Add("#user_id", user_id.ToString());
//-------------------------------------------------------------------------------------
//sends the connection, query, parameters, and query type (0 means i use a reader (select), 1 means i use non query (delete etc..))
MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
List<string> return_vals = new List<string>();
if (reader.Read())
{
//loops through the reader and adds the value to list
for (int i = 0; i < vals.Count(); i++)
{
//vals is a list of column names in the ame order they will be returned
//i think this is where it's breaking but im not certain
return_vals.Add(reader[vals[i]].ToString());
}
reader.Close();
return return_vals;
}
else
{
throw new Exception("no data");
}
}
}
class Student : User
{
public Student(MySqlConnection conn, int user_id)
{
Console.WriteLine("student created");
//list of the data i want to retrieve from the db
//must be the column names
List<string> vals = new List<string> { "user_forename", "user_surname", "user_role", "user_status"};
//should return a list with the values in the specified columns from the user with the matching id
List<string> return_vals = base.GetValues(conn, vals, user_id);
//for some reason i am getting back the column names rather than the values in the fields
foreach(var v in return_vals)
{
Console.WriteLine(v);
}
}
}
What i have tried:
- Using getstring
- Using index rather than column names
- Specifying a specific column name
- Using while (reader.Read)
- Requesting different number of columns
I have used this method during the login section and it works perfectly there (code below). I can't figure out why it doesnt work here (code above) aswell.
static Boolean Login(MySqlConnection conn)
{
Console.Write("Username: ");
string username = Console.ReadLine();
Console.Write("Password: ");
string password = Console.ReadLine();
string query = "SELECT user_id, username, password FROM Users WHERE username=#username";
Dictionary<string, string> vars = new Dictionary<string, string>
{
["#username"] = username
};
MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
Boolean valid_login = ValidLogin(reader, password);
return (valid_login);
}
static Boolean ValidLogin(MySqlDataReader reader, string password)
{
Boolean return_val;
if (reader.Read())
{
//currently just returns the password as is, I will implement the hashing later
password = PasswordHash(password);
if (password == reader["password"].ToString())
{
MainProgram.user_id = Convert.ToInt32(reader["user_id"]);
return_val = true;
}
else
{
return_val = false;
}
}
else
{
return_val = false;
}
reader.Close();
return return_val;
}
The problem is here:
string args = "";
for (int i = 0; i < vals.Count(); i++)
{
args = args + "#" + vals[i];
vars.Add("#" + vals[i], vals[i]);
// ...
}
string query = "SELECT " + args + " FROM Users WHERE user_id = #user_id";
This builds a query that looks like:
SELECT #user_forename, #user_surname, #user_role, #user_status FROM Users WHERE user_id = #user_id;
Meanwhile, vars.Add("#" + vals[i], vals[i]); ends up mapping #user_forename to "user_forename" in the MySqlParameterCollection for the query. Your query ends up selecting the (constant) value of those parameters for each row in the database.
The solution is:
Don't prepend # to the column names you're selecting.
Don't add the column names as variables to the query.
You can do this by replacing that whole loop with:
string args = string.Join(", ", vals);
I have some serous issues with this code. I have the method GetWeatherItemData that takes a parameter name and a period as input for getting data from a SQL database and it seems to work fine.
But I want to create a method that can do the same work for multiple parameters, so I created a method named GetSelectedWeatherItemsData that takes an array of parameters as input and loops through my first method, but for some reason it will only return data for 1 parameter only, the first in the array of input parameters.
Here is the first method:
public CustomDataType GetWeatherItemData(string parameterName, string fromTime, string toTime)
{
/* This method takes parameter name, start time and end time as input it will then return
* all the measurement values and their timestamp as array for the specific parameter
*/
CustomDataType getWeatherItemObj = new CustomDataType();
List<double> valueList = new List<double>();
List<string> timeStampList = new List<string>();
List<int> parameterIdList = new List<int>();
List<string> ParameterNameList = new List<string>();
try
{
using (conn = new SqlConnection(connectionString))// create and open a connection object
{
// 1. create a command object identifying the stored procedure
cmd = new SqlCommand("GetWeatherItemData", conn);
// 2.Let the command object know we will execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add the 3 parameters to command, so the can be passed to the stored procedure
cmd.Parameters.Add("#WeatherParameterName", SqlDbType.VarChar).Value = parameterName;
cmd.Parameters.Add("#FromTime", SqlDbType.VarChar).Value = fromTime;
cmd.Parameters.Add("#ToTime", SqlDbType.VarChar).Value = toTime;
//open connection
conn.Open();
// execute the command
reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
valueList.Add((double)reader["MeasurementValue"]);
timeStampList.Add(reader["MeasurementDateTime"].ToString());
parameterIdList.Add((int)reader["WeatherParameterID"]);
}
}
//close connection
reader.Close();
//changed to arrays to support webservices
getWeatherItemObj.arrayOfValue = valueList.ToArray();
getWeatherItemObj.arrayOfTimestamp = timeStampList.ToArray();
getWeatherItemObj.arrayOfParameterID = parameterIdList.ToArray();
for (counter = 0; counter < getWeatherItemObj.arrayOfValue.Length; counter++)
{
ParameterNameList.Add(GetParameterInfo(parameterName).ParameterName);
}
getWeatherItemObj.arrayOfParameterName = ParameterNameList.ToArray();
}
}
catch (SqlException e)
{
Console.WriteLine("Connection failed");
Console.WriteLine(e.Message);
Thread.Sleep(5000);
}
return getWeatherItemObj;
}
Here is the code I have problem with. It takes an array of parameter names, and period as input. But it only returns data for the first element in the input array, as if it does the for loop only once and jumps out.I tested the code inside the for loop by assigning them a fixed number like parameterName[3] instead of parameterName[counter] and this resulted in that I got data for that element not the first element. So for some reason the for loops does only 1 iteration.
public CustomDataType GetSelectedWeatherItemsData(string[] parameterName, string fromTime, string toTime)
{
CustomDataType tempObj;
List<double> valueList = new List<double>();
List<string> timeStampList = new List<string>();
List<int> paramIdStampList = new List<int>();
List<string> ParameterNameList = new List<string>();
for (counter = 0; counter < (parameterName.Length); counter++)
{
tempObj = GetWeatherItemData(parameterName[counter], fromTime, toTime);
valueList.AddRange(GetWeatherItemData(parameterName[counter], fromTime, toTime).arrayOfValue);
timeStampList.AddRange(GetWeatherItemData(parameterName[counter], fromTime, toTime).arrayOfTimestamp);
//paramIdStampList.AddRange(tempObj.arrayOfParameterID);
ParameterNameList.AddRange(GetWeatherItemData(parameterName[counter], fromTime, toTime).arrayOfParameterName);
}
getSelectedItemsObj = new CustomDataType();
getSelectedItemsObj.arrayOfValue = valueList.ToArray();
getSelectedItemsObj.arrayOfTimestamp = timeStampList.ToArray();
//getSelectedItemsObj.arrayOfParameterID = paramIdStampList.ToArray();
getSelectedItemsObj.arrayOfParameterName = ParameterNameList.ToArray();
return getSelectedItemsObj;
}
What seems definitely wrong is the fact you're calling the simple web service four times inside your loop - why don't you just call it once and then use the results you get back?
Something like:
for (counter = 0; counter < (parameterName.Length); counter++)
{
tempObj = GetWeatherItemData(parameterName[counter], fromTime, toTime);
valueList.AddRange(tempObj.arrayOfValue);
timeStampList.AddRange(tempObj.arrayOfTimestamp);
//paramIdStampList.AddRange(tempObj.arrayOfParameterID);
ParameterNameList.AddRange(tempObj.arrayOfParameterName);
}
i have this code that im getting error and, and cant understand why im getting the error. the code is as following: im using two arrays a string and a double(data values with their corresponding tinestamp). But for some reason im getting error that: index out of bounds error on this line:
getSelectedItemsObj.arrayOfTimeStamp = GetItemData(parameterName[counter], fromTime, toTime).arrayOfTimeStamp;
If i remove this line and only use arrayOfValue the code works fine, but i need both
.......... Thanks for the fast replies, here is how GetItemData is set up
public CustomDataType GetItemData(string parameterName, string fromTime, string toTime)
{
getWeatherItemObj = new CustomDataType();
// get the parameter ID
prameterID = GetParameterInfo(parameterName).ParameterID;
//get the nr of items to size value arrays
tableSize = GetTableSize(parameterName, fromTime, toTime, prameterID);
getWeatherItemObj.arrayOfValue = new double[tableSize];
getWeatherItemObj.arrayOfTimeStamp = new string[tableSize];
counter = 0;
try
{
using (conn = new SqlConnection(connectionString))// create and open a connection object
{
// 1. create a command object identifying the stored procedure
cmd = new SqlCommand("GetItemData", conn);
// 2.Let the command object know we will execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add the 3 parameters to command, so the can be passed to the stored procedure
cmd.Parameters.Add("#ParameterName", SqlDbType.VarChar).Value = parameterName;
cmd.Parameters.Add("#FromTime", SqlDbType.VarChar).Value = fromTime;
cmd.Parameters.Add("#ToTime", SqlDbType.VarChar).Value = toTime;
//open connection
conn.Open();
// execute the command
reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
getWeatherItemObj.arrayOfValue[counter] = (double)reader["MeasurementValue"];
getWeatherItemObj.arrayOfTimeStamp[counter] = reader["MeasurementDateTime"].ToString();
counter++;
}
}
//close connection
reader.Close();
}
}
catch (SqlException e)
{
Console.WriteLine("Connection failed");
Console.WriteLine(e.Message);
Thread.Sleep(5000);
}
return getWeatherItemObj;
}
class CustomDataType
{
public double[] arrayOfValue;
public string[] arrayOfTimeStamp;
}
public CustomDataType GetSelectedtemsData(string[] parameterName, string fromTime, string toTime)
{
numberOfParameters = parameterName.Length;//Get the number of given parameters
tableSize = 0;
for (counter = 0; counter < numberOfParameters; counter++)
{
tableSize = tableSize + GetItemData(parameterName[counter], fromTime, toTime).arrayOfTimeStamp.Length;
}
getSelectedItemsObj = new CustomDataType();
getSelectedItemsObj.arrayOfValue = new double[tableSize];
getSelectedItemsObj.arrayOfTimeStamp = new string[tableSize];
for (counter = 0; counter < tableSize; counter++)
{
getSelectedItemsObj.arrayOfValue = GetItemData(parameterName[counter], fromTime, toTime).arrayOfValue;
getSelectedItemsObj.arrayOfTimeStamp = GetItemData(parameterName[counter], fromTime, toTime).arrayOfTimeStamp;
}
return getSelectedItemsObj;
}
The problem is right here:
for (counter = 0; counter < tableSize; counter++)
{
getSelectedItemsObj.arrayOfValue = GetItemData(parameterName[counter], fromTime, toTime).arrayOfValue;
getSelectedItemsObj.arrayOfTimeStamp = GetItemData(parameterName[counter], fromTime, toTime).arrayOfTimeStamp;
}
Your counter size is being incremented based on tableSize, but its being used as if its based on the size of parameterName. Nothing in your code enforces this assumption, so as soon as tableSize is larger than parameterName, you will get the error you are seeing.
The problem is in how you're treating your counter. If you remove the timestamp stuff, the counter never really gets modified so it all appears to work, but if you have the timestamp stuff in there, then your for loop initializer looks like this:
for (counter = 0; counter < tableSize; counter++)
where tableSize is ultimately greater than parameterName[].Length. Since later you're calling parameterName[counter], counter will be out of bounds. You need to make sure that you're never attempting to access something in parameterName[] by an index that is not legal within that array.
Edit:
Another possibility, if removing only that line removes the error, is that the return of
GetItemData(parameterName[counter], fromTime, toTime).arrayOfTimeStamp;
is larger than the specified array allocated in
getSelectedItemsObj.arrayOfTimeStamp = new string[tableSize];
In order to make such a determination, you would need to post the code to that method as well.
Please try the following:
public CustomDataType GetSelectedtemsData(string[] parameterName, string fromTime, string toTime)
{
CustomDataType tempObj; // *Rename this variable*
List<double> valueList = new List<double>();
List<string> timeStampList = new List<string>();
for (counter = 0; counter < parameterName.Length; counter++)
{
tempObj = GetItemData(parameterName[counter], fromTime, toTime);
valueList.AddRange(tempObj.arrayOfValue);
timeStampList.AddRange(tempObj.arrayOfTimeStamp);
}
getSelectedItemsObj = new CustomDataType();
getSelectedItemsObj.arrayOfValue = valueList.ToArray();
getSelectedItemsObj.arrayOfTimeStamp = timeStampList.ToArray();
return getSelectedItemsObj;
}
I was going to try it your way, but once I realized you were pulling each parameterName 3 times, and the second loop would need an inner loop (since you would need to iterate through each index in each GetItemData), and that my fix would have resulted in multiple copies of the same data anyways; I decided to rebuild the method using two List.
If this does not solve your issue then I will need the complete error message, the stack trace from the error message, and the code of the top most method on the error stack.
Note: There are a number of additional optimizations which may help you like:
You may also want to update GetItemData to also use List instead of arrays so you can skip the tableSize = GetTableSize(parameterName, fromTime, toTime, prameterID); line.
You may want to change CustomDataType so arrayOfValue and arrayOfTimeStamp are not arrays. Then, instead of passing a CustomDataType out you could pass a CustomDataType[] or even List<CustomDataType>.
I am trying to loop thru the elements of an Array[] for Parameter names and Object[] for object values using the AddWithValue().
Unfortunately it is saying "Procedure or function 'sp_add_Request' expects parameter '#RequestType', which was not supplied". When I run to cursor, I can see all the parameters are supplied, I do not understand where the problem is. Please help. See code below:
object[] myValues = new Object[] { txtID.Text, ddlAmissionType.Text };
string[] paramsNames = new string[] { "#CHI", "#RequestType"};
dbConn.addData("sp_add_Request", paramsNames, myValues, lbMsg.Text);
Parent method:
public static bool addData(string storedProcName, string[] dynamicParamName, object[] aramVals, string msg)
{
for (int i = 0; i < dynamicParamName.Length; i++)
{
cmd2.Parameters.AddWithValue(dynamicParamName[i], paramVals[i]);
//cmd2.Parameters.Add(dynamicParamName[i], dynamicParamValues[i]);
try
{
if (cmd2.Connection.State == ConnectionState.Closed)
{
cmd2.Connection.Open();
int stat = cmd2.ExecuteNonQuery();
if (stat > 0)
{
res = true;
msg = "Recorded Added successfully";
cmd2.Connection.Close();
cmd2.Dispose();
}
}
}
}
You are accessing the database in your loop because the command is executed within the for loop. So you're performing your command before the 2nd parameter is added. Move the try block outside the for loop and you should be fine.
public static bool addData(string storedProcName, string[] dynamicParamName, object[] paramVals, string msg)
{
for (int i = 0; i < dynamicParamName.Length; i++)
{
cmd2.Parameters.AddWithValue(dynamicParamName[i], paramVals[i]);
//cmd2.Parameters.Add(dynamicParamName[i], dynamicParamValues[i]);
}
try
{
if (cmd2.Connection.State == ConnectionState.Closed)
{
cmd2.Connection.Open();
}
int stat = cmd2.ExecuteNonQuery();
if (stat > 0)
{
res = true;
msg = "Recorded Added successfully";
cmd2.Connection.Close();
cmd2.Dispose();
}
}
}
You may want to just go ahead and put your connection object in a using statement that way it's automatically disposed. #abatishchev's answer below shows the proper way to handle your ado objects.
Create, use and dispose new connection/command objects each time method is being called. This will use connection pooling and other performance positive techniques.
public static bool addData(string storedProcName, string[] dynamicParamName, object[] paramVals, string msg)
{
SqlParameter[] paramArr = new SqlParameter[dynamicParamName.Length];
for(int i = 0; i < dynamicParamName.Length; i++)
{
paramArr[i] = new SqlParameter(dynamicParamName[i], paramVals[i]);
}
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = commandText;
//command.CommandType = CommandType.StoredProcedure ; // if needed
command.Parameters.AddRange(paramArr);
connection.Open();
return command.ExecuteNonQuery() > 0;
}
}
See MSDN: SqlParameterCollection.AddRange() method.
Also you can use LINQ:
SqlParameter[] paramArr = dynamicParamName
.Select((paramName,i) => new SqlParameter(paramName, paramVals[i]).ToArray();
or
SqlParameter[] paramArr = Enumerable.Range(0, dynamicParamName.Length - 1)
.Select(i => new SqlParameter(dynamicParamName[i], paramVals[i])
.ToArray();