I have a ugly code that can't be reused. I have many similar queries. I want to rewrite it with SqlParameterCollectionExtensions or other better ways. But I don't know about SqlParameterCollectionExtensions at all.
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
SqlConnection con = new SqlConnection(strCon);
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "UPDATE Problem_DE SET ProbDesc = #ProbDesc, field_1 = #field_1, field_2 = #field_2, field_3 = #field_3, field_4 = #field_4, field_5 = #field_5, field_6 = #field_6, field_7 = #field_7 WHERE (ProbId = #ProbId)";
if (e.NewValues["ProbDesc"] == null)
cmd.Parameters.AddWithValue("#ProbDesc", DBNull.Value);
else
cmd.Parameters.AddWithValue("#ProbDesc", e.NewValues["ProbDesc"]);
if (e.NewValues["field_1"] == null)
cmd.Parameters.AddWithValue("#field_1", DBNull.Value);
else
cmd.Parameters.AddWithValue("#field_1", e.NewValues["field_1"]);
if (e.NewValues["field_2"] == null)
cmd.Parameters.AddWithValue("#field_2", DBNull.Value);
else
cmd.Parameters.AddWithValue("#field_2", e.NewValues["field_2"]);
if (e.NewValues["field_3"] == null)
cmd.Parameters.AddWithValue("#field_3", DBNull.Value);
else
cmd.Parameters.AddWithValue("#field_3", e.NewValues["field_3"]);
if (e.NewValues["field_4"] == null)
cmd.Parameters.AddWithValue("#field_4", DBNull.Value);
else
cmd.Parameters.AddWithValue("#field_4", e.NewValues["field_4"]);
\\ blah blah
cmd.ExecuteNonQuery();
con.Close();
}
The sql parameters come from e or textbox etc.
Thanks.
Maybe something like this? I assume the problem is that you have a variable number of values, depending on the problem table?
private void UpdateProblem(string problemName, string problemDescription, int problemId, object[] fieldValues)
{
SqlConnection con = null;
SqlCommand cmd = new SqlCommand();
StringBuilder sql = new StringBuilder();
int fieldCounter = 1;
// start building the sql statement
sql.AppendFormat("UPDATE {0} SET ProbDesc = #ProbDesc", problemName);
// add the 'description' parameter
cmd.Parameters.Add(new SqlParameter("#ProbDesc", problemDescription));
// add each field value to the update statement... the SqlParameter will infer the database type.
foreach(object fieldValue in fieldValues)
{
// add additional SET clauses to the statement
sql.AppendFormat(",field{0} = #field{0}", fieldCounter);
// add the field parameter to the command's collection
cmd.Parameters.Add(new SqlParameter(String.Format("#field{0}", fieldCounter), fieldValue));
fieldCounter++;
}
// finish up the SQL statement by adding the where clause
sql.Append(" WHERE (ProbId = #ProbId)");
// add the 'problem ID' parameter to the command's collection
cmd.Parameters.Add(new SqlParameter("#ProbId", problemId));
// finally, execute the SQL
try
{
con.Open();
cmd.Connection = con;
cmd.CommandText = sql.ToString();
cmd.ExecuteNonQuery();
}
catch(SqlException ex)
{
// do some exception handling
}
finally
{
if(con != null)
con.Dispose();
}
}
An example to call this code would be:
public void UpdateProblemDe()
{
int problemId = FetchCurrentProblemId();
string field1 = e.NewValues["field_1"];
string field2 = e.NewValues["field_2"];
string field3 = ddlField3.SelectedValue;
int field4 = Convert.ToInt32(e.NewValues["field_4"]);
string field5 = txtField5.Text;
DateTime field6 = DateTime.Now.AddSeconds(Convert.ToInt32(ddlField6.SelectedValue));
string field7 = txtField7.Text;
object[6] fieldValues;
if(field1 != null)
fieldValues[0] = field1;
else
fieldValues[0] = DBNull.Value;
if(field2 != null)
fieldValues[1] = field2;
else
fieldValues[1] = DBNull.Value
fieldValues[2] = field3;
fieldValues[3] = field4;
fieldValues[4] = field5;
fieldValues[5] = field6;
fieldValues[6] = field7;
UpdateProblem("Problem_DE", "Houston, we have a problem", problemId, fieldValues);
}
The example code above is obviously just a demonstration of how to make an array of objects stored from page control values and doesn't include any data validation that you will need to implement in production code.
If you won't know how big the object[] array needs to be at runtime, you can change it to be a generic List of objects and add the items dynamically.
Based on this answer
Create new SQLCommand's or reuse the same one
you could refactor your code the following way
public class DbHepler
{
private readonly string _connectionString;
public DbHepler(string connectionString)
{
_connectionString = connectionString;
}
public void ExecuteNonQuery(string query)
{
ExecuteNonQuery(query, null);
}
public void ExecuteNonQuery(string query, Dictionary<string, object> parameters)
{
using (SqlConnection conn = new SqlConnection(_connectionString))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = query;
if (parameters != null)
{
foreach (string parameter in parameters.Keys)
{
cmd.Parameters.AddWithValue(parameter, parameters[parameter] ?? DBNull.Value);
}
}
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
}
your code will look something like:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string query = "UPDATE Problem_DE SET ProbDesc = #ProbDesc, field_1 = #field_1, field_2 = #field_2, field_3 = #field_3, field_4 = #field_4, field_5 = #field_5, field_6 = #field_6, field_7 = #field_7 WHERE (ProbId = #ProbId)";
Dictionary<string, object> parameters = new Dictionary<string, object>();
if (e.NewValues["ProbDesc"] == null)
parameters.Add("#ProbDesc", null);
else
parameters.Add("#ProbDesc", e.NewValues["ProbDesc"]);
//blah blah
DbHepler dbHepler = new DbHepler("your sql connection info");
dbHepler.ExecuteNonQuery(query, parameters);
}
Related
I am trying to get int value from the database but It is throwing an error
Unable to cast object of type 'System.Byte' to type 'System.Int32'.
In the database, Active field is tinyint.
Also, how to return both values from this method.
private string CheckData(string firstValue, string SecondValue, int Active)
{
string Data = "";
StringBuilder sb = new StringBuilder();
string query = #"select M.ident Mi, mmp.active Active
from Iden.Iden M
inner join PtM.MPt MMP on MMP.mPat = M.id
where M.ident = 'firstValue'
and Mi.ident = 'SecondValue'";
sb.Append(query);
sb.Replace("firstValue", firstValue);
sb.Replace("SecondValue", SecondValue);
SqlConnection connection = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sb.ToString());
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
try
{
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Data = reader.GetString(reader.GetOrdinal("Mi"));
Active = reader.GetInt32(reader.GetOrdinal("Active"));
}
}
}
catch (Exception ex)
{
_log.Error($"Exception:{ex.Message}");
}
finally
{
connection.Close();
connection.Dispose();
}
return Data;
}
Here's a stab at it. I can't debug it (since I don't feel like creating a database).
First I create a type to hold the results. You could just use a Tuple, but this seems clearer:
public class DataActive
{
public string Data { get; set; }
public byte Active { get; set; }
}
I make your function return a collection of these - it's not obvious from your code that there is only one.
You'll also notice that I use SqlParameters to add firstValue and secondValue to your query. Look up SQL Injection (and Little Bobby Tables).
If you are using a recent version of C# (which I don't), there's a new syntax for using that requires less indenting. The using statements stick a call to Dispose in a finally statement at the end of the block. Also note that I'm disposing the SqlCommand and the DataReader
public static IEnumerable<DataActive> CheckData(string firstValue, string secondValue)
{
var results = new List<DataActive>();
const string query = #"select M.ident Mi,mmp.active Active from Iden.Iden M
Inner join PtM.MPt MMP on MMP.mPat =M.id
where M.ident = #firstValue and Mi.ident = #secondValue";
using (var connection = new SqlConnection(connString))
{
using (var cmd = new SqlCommand(query))
{
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.Add("#firstValue", SqlDbType.NVarChar, 50).Value = firstValue;
cmd.Parameters.Add("#secondValue", SqlDbType.NVarChar, 50).Value = secondValue;
try
{
connection.Open();
using (var reader = cmd.ExecuteReader())
{
var dataOrdinal = reader.GetOrdinal("Mi");
var activeOrdinal = reader.GetOrdinal("Active");
if (reader.HasRows)
{
while (reader.Read())
{
results.Add(new DataActive
{
Data = reader.GetString(dataOrdinal),
Active = reader.GetByte(activeOrdinal),
});
}
}
}
}
catch (Exception ex)
{
_log.Error($"Exception:{ex.Message}");
}
}
}
return results;
}
If your TINY_INT Active represents a boolean value, figure out what the rule is, and do a conversion after you get the value using reader.GetByte.
One final note, it's often better to log ex.ToString() rather than ex.Message. You get the message and the stack that way.
I'm trying to adding to table access and datagrid row with sql query. buy without a success. Any ideas ? Thank's
My sql query :
DataBaseIkuns.Instance.InsertToDB(string.Format(DictionaryUtilsDB.dictioneary[DictionaryUtilsDB.CommendTypes.AddObserver], o.ID_Observer, o.Lat, o.Long, o.azimuth));
public static Dictionary<CommendTypes, string> dictioneary = new Dictionary<CommendTypes, string>
{
{CommendTypes.AddObserver,"Insert into ShowTableObserver(ID_Ob,Lat,Long,Azimuth)"
+"values('{0}','{1}','{2}','{3}')"},
{CommendTypes.AzimuthLongLatFromOB,"SELECT ID_Observer,Longitude,Latitude,Azimuth FROM Observer Where ID_Observer = {0}"}
};
public void InsertToDB(string sql) // It get the right values - 1,2,3,4
{
int insert = 0;
try
{
if (con.State.ToString()== "Open")
{
cmd = new OleDbCommand();
oledbAdapter = new OleDbDataAdapter();
dt = new DataTable();
cmd.Connection = con;
cmd.CommandText = sql;
insert = cmd.ExecuteNonQuery(); // Here it jump's to the catch. why ?
if (insert > 0)
{
MessageBox.Show("Your Insert successed");
}
else
{
MessageBox.Show("Your Insert failed");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Have a comment in the code where the program falls.
The value of sql when it falls :
Insert into ShowTableObserver(ID_Ob,Lat,Long,Azimuth)values('3','31.4','34','150')
If you use an Access Database behind the OleDb provider then you have a problem with the word LONG. It is a reserved keyword (and probably it is the same in many other database systems). In this case you need to encapsulate the field name in square brackets
{CommendTypes.AddObserver,"Insert into ShowTableObserver(ID_Ob,Lat,[Long],Azimuth)"
Said that you need to start to use parameterized query. Your string.Format is another kind of string concatenation that leads to Sql Injection, parsing problems and subtle syntax error when you miss a single quote or other type specifier in your query string
For example
public static Dictionary<CommendTypes, string> dictioneary = new Dictionary<CommendTypes, string>
{
{CommendTypes.AddObserver,"Insert into ShowTableObserver(ID_Ob,Lat,Long,Azimuth)"
+"values(?,?,?,?)"},
{CommendTypes.AzimuthLongLatFromOB,"SELECT ID_Observer,Longitude,Latitude,Azimuth "
+"FROM Observer Where ID_Observer = ?"}
};
public void InsertToDB(string sql, List<OleDbParameter> parameters)
{
int insert = 0;
try
{
if (con.State.ToString()== "Open")
{
using(cmd = new OleDbCommand());
{
cmd.Connection = con;
cmd.CommandText = sql;
cmd.Parameters.AddRange(parameters.ToArray());
insert = cmd.ExecuteNonQuery();
}
........
}
}
......
}
Now when you call the InsertDB you write
DataBaseIkuns.Instance.InsertToDB(string.Format(DictionaryUtilsDB.dictioneary[DictionaryUtilsDB.CommendTypes.AddObserver], , o.Lat, o.Long, o.azimuth));
List<OleDbParameter> parameters = new List<OleDbParameter>();
parameters.Add(new OleDbParameter())
{
ParameterName = "#p1", OleDbType= OleDbType.VarWChar, Value = o.ID_Observer
}
parameters.Add(new OleDbParameter())
{
ParameterName = "#p2", OleDbType= OleDbType.VarWChar, Value = o.Lat
}
parameters.Add(new OleDbParameter())
{
ParameterName = "#p3", OleDbType= OleDbType.VarWChar, Value = o.Long
}
parameters.Add(new OleDbParameter())
{
ParameterName = "#p4", OleDbType= OleDbType.VarWChar, Value = o.Azimuth
}
DataBaseIkuns.Instance.InsertToDB(
DictionaryUtilsDB.dictioneary[DictionaryUtilsDB.CommendTypes.AddObserver], parameters);
I want to make a library system in C#. In this system when a book is issued it should automatically reduce the book quantity in database. When book quantity == 0 there should be a message box showing "not available".
This is my code:
private void btnIssue_Click(object sender, EventArgs e)
{
if (cmbResID.Text != "" && cmbMemID.Text != "" && cmbBookID.Text != "" && txtBkTitle.Text != "" && txtCategory.Text != "" && txtAuthor.Text != "" && txtIssueDate.Text != "" && txtActDate.Text != "")
{
SqlCommand Quantity = new SqlCommand("Select * from tblBookDetails where Book_ID = '" + cmbBookID.Text +"'");
DataSet ds = Library.Select(Quantity);
if (ds.Tables[0].Rows.Count > 0)
{
textBox1.Text = ds.Tables[0].Rows[0].ItemArray.GetValue(5).ToString();
int b = Convert.ToInt32(textBox1.Text);
if (b > 0)
{
//a = a - 1;
//int b = Convert.ToInt32(a);
//label15.Text = a.ToString();
SqlCommand update=new SqlCommand("UPDATE tblBookDetails SET Quantity=Quantity-1 WHERE Book_ID='"+ cmbBookID +"'");
Library.ExecuteInsert(update);
SqlCommand save = new SqlCommand("insert into tblBookIssue values(#ResID,#Member_ID,#Book_ID,#Issue_Date,#Act_Ret_Date)");
save.Parameters.AddWithValue("#ResID", cmbResID.Text);
save.Parameters.AddWithValue("#Member_ID", cmbMemID.Text);
save.Parameters.AddWithValue("#Book_ID", cmbBookID.Text);
save.Parameters.AddWithValue("#Issue_Date", txtIssueDate.Text);
save.Parameters.AddWithValue("#Act_Ret_Date", txtActDate.Text);
Library.Insert(save);
MessageBox.Show("Book Issued", "Book Issue", MessageBoxButtons.OK, MessageBoxIcon.Information);
clear();
}
else
{
MessageBox.Show("this book is not available");
}
}
}
else
{
MessageBox.Show("FILL COLUMS");
}
}
Executing SQL based off of text boxes is very unsafe and Prone to SQL injection attacks. Also, to follow Object Oriented program and make much cleaner code it would be advisable to make a Book object, I completed some code below which shows an example including the book incrementer. It would be better to make focused stored procs which execute gets for books and updates for book checkouts. You will have to turn your basic select into a stored proc, and write another proc which looks at the quantity and if quantity < 1 return 0 else return 1. Let me know if you need more info, this code should help you get rolling
using System;
using System.Data;
using System.Data.SqlClient;
namespace MockLibrary
{
internal class Book
{
#region Constructors
public Book()
{
}
public Book(string resId, string memberId, string bookId, DateTime issueDate, DateTime actRetDate)
{
this.ResId = resId;
this.MemberId = memberId;
this.BookId = bookId;
this.IssueDate = issueDate;
this.ActRetDate = actRetDate;
}
#endregion
#region Properties
private string _ResID;
private string _MemberID;
private string _BookId;
private DateTime _IssueDate;
private DateTime _ActRetDate;
public string ResId
{
get { return _ResID; }
set { _ResID = value; }
}
public string MemberId
{
get { return _MemberID; }
set { _MemberID = value; }
}
public string BookId
{
get { return _BookId; }
set { _BookId = value; }
}
public DateTime IssueDate
{
get { return _IssueDate; }
set { _IssueDate = value; }
}
public DateTime ActRetDate
{
get { return _ActRetDate; }
set { _ActRetDate = value; }
}
#endregion
public Book GetBookByID(string resId, string memberId)
{
try
{
using (SqlConnection con = new SqlConnection("put your db con string here"))
{
using (SqlCommand cmd = new SqlCommand("sp_GetBookById", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ResId", SqlDbType.VarChar).Value = resId;
cmd.Parameters.Add("#MemberId", SqlDbType.VarChar).Value = memberId;
con.Open();
cmd.ExecuteNonQuery();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Book newBook = new Book(rdr["ResId"].ToString(),rdr["MemberId"].ToString(),rdr["BookId"].ToString(),DateTime.Now,DateTime.Now);
return newBook;
}
}
}
}
catch
{
throw new Exception("something went wrong");
}
return null;
}
public bool CheckoutBook(string resId, string memberId)
{
using (SqlConnection con = new SqlConnection("put your db con string here"))
{
using (SqlCommand cmd = new SqlCommand("sp_CheckoutBook", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ResId", SqlDbType.VarChar).Value = resId;
cmd.Parameters.Add("#MemberId", SqlDbType.VarChar).Value = memberId;
con.Open();
cmd.ExecuteNonQuery();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
if (rdr["checkoutsuccessful"].ToString() == "1")
{
return true;
}
}
}
}
return false;
}
}
}
when user returns a book:-
MySqlCommand cm1;
cm1 = new MySqlCommand("update addbook set bookquantity=bookquantity+1 where bookname='" + txt_bookname.Text + "'",con);
cm1.ExecuteNonQuery();
I want to implement a simple delete button for my database. The event method looks something like this:
private void btnDeleteUser_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure?", "delete users",MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
command = new SqlCommand();
try
{
User.connection.Open();
command.Connection = User.connection;
command.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
int flag;
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
command.Parameters.AddWithValue("#id", rowUserID);
flag = command.ExecuteNonQuery();
if (flag == 1) { MessageBox.Show("Success!"); }
dgvUsers.Rows.Remove(row);
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (ConnectionState.Open.Equals(User.connection.State))
User.connection.Close();
}
}
else
{
return;
}
}
but I get this message:
A variable #id has been declared. Variable names must be unique within
a query batch or stored procedure.
Is there any way to reuse this variable?
Parameters.AddWithValue adds a new Parameter to the command. Since you're doing that in a loop with the same name, you're getting the exception "Variable names must be unique".
So you only need one parameter, add it before the loop and change only it's value in the loop.
command.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
command.Parameters.Add("#id", SqlDbType.Int);
int flag;
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
command.Parameters["#id"].Value = rowUserID;
// ...
}
Another way is to use command.Parameters.Clear(); first. Then you can also add the parameter(s) in the loop without creating the same parameter twice.
Rather than:
command.Parameters.AddWithValue("#id", rowUserID);
Use something like:
System.Data.SqlClient.SqlParameter p = new System.Data.SqlClient.SqlParameter();
Outside the foreach, and just set manually inside the loop:
p.ParameterName = "#ID";
p.Value = rowUserID;
I would use this:
public static class DbExtensions
{
public static void AddParameter(SQLiteCommand command, string name, DbType type, object value)
{
var param = new SQLiteParameter(name, type);
param.Value = value;
command.Parameters.Add(param);
}
}
Then, call this:
DbExtensions.AddParameter(command, "#" + fieldOfSearch[i], DbType.String, value[i]);
Error is because you are adding the same parameter again and again in each iteration of the loop.
I would move that code to a seperate method so that i can call it from multiple places as needed.
public bool DeleteUser(int userId)
{
string connString = "your connectionstring";
try
{
using (var conn = new SqlConnection(connString))
{
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
cmd.Parameters.AddWithValue("#id", userId);
conn.Open();
cmd.ExecuteNonQuery();
return true;
}
}
}
catch(Exception ex)
{
//Log the Error here for Debugging
return false;
}
}
Then call it like this
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
if(dgvUsers[0,selectedIndex]!=null)
{
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
var result=DeleteUser(rowUserID)
}
else
{
//Not able to get the ID. Show error message to user
}
}
First time user - hoping this is in the right format:
I am wanting to know if I can create SQL DbParameter values, esp on the ParamaterName.
My current code is:
DbCommand dbCommand = SqlDb.GetStoredProcCommand(uspCommand);
DbParameter ProcessedFileName = dbCommand.CreateParameter();
ProcessedFileName.DbType = DbType.String;
ProcessedFileName.ParameterName = "#FileName";
ProcessedFileName.Value = pstrProcessedFileName;
dbCommand.Parameters.Add(ProcessedFileName);
I am wanting to add:
ProcessedFileName.ParameterName = "#FileName1";
ProcessedFileName.ParameterName = "#FileName2";
ProcessedFileName.ParameterName = "#FileName3";
ProcessedFileName.ParameterName = "#FileName4";
with the #FileNames coming from an array.
Something like this should work:
DbCommand dbCommand = SqlDb.GetStoredProcCommand(uspCommand);
foreach(String param in MyParameters)
{
DbParameter ProcessedFileName = dbCommand.CreateParameter();
ProcessedFileName.DbType = DbType.String;
ProcessedFileName.ParameterName = param;
ProcessedFileName.Value = pstrProcessedFileName;
dbCommand.Parameters.Add(ProcessedFileName);
}
best way to do this is put them in Dictionary, because you will need value also
Dictionary<string, string> params = new Dictionary<string,string>();
and just add them many as you want
params.Add("#FileName1", "my_filename")
etc...
and then
foreach(var param in params)
dbCommand.Parameters.AddWithValue(param.Key, param.Value);
Creating dynamic SQL DbParameter values
This is very helpful when you are going to create project where there is dynamic database, or may in future you are going to migrate / switch database .
Here is step by step solution
step 1) Create Parameter structure
public struct Parameter
{
public string ParameterName { get; set; }
public ParameterDirection Direction { get; set; }
public DbType DbType { get; set; }
public object Value { get; set; }
public string SourceColumn { get; set; }
public int Size { get; set; }
}
Step 2) Create database handling class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;
using System.Data.Common;
using MySql.Data.MySqlClient;
using MySql.Data;
using Oracle.DataAccess;
using Oracle.DataAccess.Client;
public class DBManagement
{
string connectionStr;
DbConnection con;
DbCommand cmd;
DbDataAdapter AD;
DataSet ds;
DbParameter[] sp;
IDBManagement Iobj = null;
public DBManagement()
{
this.Initialize();
}
void Initialize()
{
try
{
switch (ConfigurationManager.AppSettings["ActiveDatabase"].ToUpper())
{
case "MSSQL":
connectionStr = ConfigurationManager.ConnectionStrings["MSSQLConnectionString"].ConnectionString;
con = new SqlConnection();
cmd = new SqlCommand();
AD = new SqlDataAdapter();
break;
case "ORACLE":
connectionStr = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
con = new OracleConnection();
cmd = new OracleCommand();
AD = new OracleDataAdapter();
break;
case "MYSQL":
connectionStr = ConfigurationManager.ConnectionStrings["MYSQLConnectionString"].ConnectionString;
con = new MySqlConnection();
cmd = new MySqlCommand();
AD = new MySqlDataAdapter();
break;
default:
break;
}
con.ConnectionString = connectionStr;
cmd.Connection = con;
}
catch (Exception ex)
{
}
}
public DataSet ExecuteProcedure(string procName, CommandType cmdType, Parameter[] DBParameters = null)
{
try
{
cmd.CommandText = procName;
cmd.CommandType = cmdType;
cmd.Parameters.Clear();
if (DBParameters != null && DBParameters.Length > 0)
{
sp = DBParameters.ToParamerArray(cmd);
cmd.Parameters.AddRange(sp);
}
ds = new DataSet();
AD.SelectCommand = cmd;
AD.Fill(ds);
return ds;
}
catch (Exception ex)
{
throw ex;
}
}
}
Step 3) Convert parameter as per database
public static partial class GlobalExtensionFunctions
{
public static DbParameter[] ToParamerArray(this Parameter[] parameters,DbCommand cmd)
{
DbParameter[] sp = new DbParameter[parameters.Length];
int i = 0;
foreach (Parameter parameter in parameters)
{
// DbParameter p = cmd.CreateParameter();
sp[i] = cmd.CreateParameter();
sp[i].ParameterName = parameter.ParameterName;
sp[i].Value = parameter.Value;
sp[i].Direction = string.IsNullOrEmpty(Convert.ToString(parameter.Direction)) || parameter.Direction==0 ? ParameterDirection.Input : parameter.Direction;
sp[i].DbType = parameter.DbType;
sp[i].SourceColumn = parameter.SourceColumn;
sp[i].Size = parameter.Size;
i++;
}
return sp;
}
}
Step 4) Get Data
DBManagement c = new DBManagement();
public DataSet GetGetTestList(int testId)
{
Parameter[] p = new Parameter[1];
p[0].ParameterName = "#TestId";
p[0].Value = testId;
p[0].DbType = DbType.Int32;
return c.ExecuteProcedure(Procedures.TestDetails, CommandType.StoredProcedure,p);
}
Now use dataset or datatable and enjoy! :)
Abe - thanks - you got me in the right direction. Here is what I ended up doing:
inside my foreach loop, I'm calling my method:
foreach (DataRow row in GlobalClass.NAVdataTable.Rows)
{
GlobalClass.AddToDbCommand(ref dBCommand, row["FieldName"].ToString(), row["Value"].ToString());
connection.Open();
SqlDb.ExecuteNonQuery(dBCommand);
connection.Close();
dBCommand.Parameters.Clear();
}
and then my AddToDbCommand method contains:
public static void AddToDbCommand(ref DbCommand dbCommand, string FieldName, string FieldValue)
{
string FieldNameParameter = "#" + FieldName;
DbParameter dbParameter = dbCommand.CreateParameter();
dbParameter.ParameterName = FieldNameParameter;
dbParameter.Value = FieldValue;
dbCommand.Parameters.Add(dbParameter);
}
Refactored as an extension to DbCommand, also fieldName is left without #, so you need to pass # or : prefixes and fieldValue is set to object type (not only string).
public static class DbCommandExtensions
{
public static void AddParam(this DbCommand dbCommand, string fieldName, object fieldValue)
{
string fieldNameParameter = fieldName;
DbParameter dbParameter = dbCommand.CreateParameter();
dbParameter.ParameterName = fieldNameParameter;
dbParameter.Value = fieldValue;
dbCommand.Parameters.Add(dbParameter);
}
}