How to Reuse Logic Without Copy/Pasting Blocks of Code - C# - c#

My project reuses the code below multiple times with only a few variables changing. I've noted the values that change with e.g. ***value***.
if (comboBox1.Text == ***"Most recent first"***)
{
string dgvconn = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\n0740572\Projects\CW\CW\bin\Debug\Database1.mdf;Integrated Security=True";
string sql = "select * from Records where UserID = #userID Order By ***Date Desc***";
SqlConnection connection = new SqlConnection(dgvconn);
SqlDataAdapter dataadapter = new SqlDataAdapter(sql, connection);
dataadapter.SelectCommand.Parameters.AddWithValue("#userID", currentUserID);
DataSet ds = new DataSet();
connection.Open();
dataadapter.Fill(ds, "Records");
connection.Close();
recordsDataGridView.DataSource = ds;
recordsDataGridView.DataMember = "Records";
}
How can I use this same logic, with different values, without copying and pasting the if statement multiple times?

Sounds to me you want something like:
private void foo(string matchText, string sortBy) {
if (comboBox1.Text == matchText)
{
string dgvconn = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\n0740572\Projects\CW\CW\bin\Debug\Database1.mdf;Integrated Security=True";
string sql = "select * from Records where UserID = #userID Order By " + sortBy;
SqlConnection connection = new SqlConnection(dgvconn);
SqlDataAdapter dataadapter = new SqlDataAdapter(sql, connection);
dataadapter.SelectCommand.Parameters.AddWithValue("#userID", currentUserID);
DataSet ds = new DataSet();
connection.Open();
dataadapter.Fill(ds, "Records");
connection.Close();
recordsDataGridView.DataSource = ds;
recordsDataGridView.DataMember = "Records";
}
}//foo
//Call the method
foo("Most recent first", "Date DESC");
foo("Most recent last", "Date");
foo("By Username", "User");

Related

Best way to debug parameterized query in c# [duplicate]

This question already has answers here:
Get the generated SQL statement from a SqlCommand object?
(25 answers)
Closed 6 years ago.
Escape ( ' ) symbol in Textbox for asp.net c#
Based on the question in post above, most people suggested that "parameterized query" is the best solution to avoid the sql injection.
Below is my code by using the sql injection
public DataSet checkemp(string user)
{
strsql = "SELECT * from employee where employeeid = #userid";
SqlConnection con = new SqlConnection(connectionString);
SqlDataAdapter da = new SqlDataAdapter(strsql, connectionString);
da.SelectCommand.Parameters.Add("#userid", SqlDbType.VarChar, 50).Value = user;
// pretend the user name is "Micheal"
con.Open();
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
con.Dispose();
return ds;
}
During the debugging, I can only get the query "SELECT * from employee where employeeid = #userid" if I point on "strsql" label, but not "SELECT * from employee where employeeid = 'Micheal'.
Any solution suggested to solve this question and make it most efficiency? thanks everyone!
I would introduce an extension method (although this is not must, actual logic is more important) that returns the parsed query as below, and call that only during debug mode:
public void TestMethod()
{
string cmdStr = "<some sql command text>";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(cmdStr, con);
cmd.Parameters.AddWithValue("<param1>", <value1>); // add parameter in any way you want
#if DEBUG
string parsedQuery = cmd.GetParsedQuery();
Console.WriteLine(parsedQuery); // or whatever
#endif
SqlDataAdapter da = new SqlDataAdapter(cmd);
con.Open();
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
con.Dispose();
return ds;
}
public static string GetParsedQuery(this SqlCommand cmd)
{
if(cmd.CommandType == CommandType.Text)
{
string parsedQuery = cmd.CommandText;
foreach(var p in cmd.Parameters)
{
parsedQuery = parsedQuery.Replace(p.ParameterName, Convert.ToString(p.Value));
}
return parsedQuery;
}
return null;
}
Note that, although I have directly written extension method (for brevity), it should really be defined in a separate static class.
Try MiniProfiler :
"An ADO.NET profiler, capable of profiling calls on raw ADO.NET"
http://miniprofiler.com/
public DataSet checkemp(string user)
{
strsql = "SELECT * from employee where employeeid = #userid";
SqlConnection con = GetOpenConnection(connectionString);
SqlDataAdapter da = new SqlDataAdapter(strsql, connectionString);
da.SelectCommand.Parameters.Add("#userid", SqlDbType.VarChar, 50).Value = user;
// pretend the user name is "Micheal"
con.Open();
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
con.Dispose();
return ds;
}
public static DbConnection GetOpenConnection(string connectionString)
{
var cnn = new SqlConnection(connectionString);
// wrap the connection with a profiling connection that tracks timings
return new StackExchange.Profiling.Data.ProfiledDbConnection(cnn, MiniProfiler.Current);
}
** You might need to wrap SqlCommand with ProfiledDbCommand

Issue while deleting row using DataSet

Following code does not delete a row from dataset and dont update the database....
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
SqlConnection con = new SqlConnection();
con.ConnectionString = cs;
SqlDataAdapter adpt = new SqlDataAdapter("Select *from RegisterInfoB", con);
ds = new DataSet();
adpt.Fill(ds, "RegisterTable");
foreach (DataRow dr in ds.Tables[0].Rows)
{
if (dr["FirstName"] == "praveen")
{
dr.Delete();
}
}
ds.Tables[0].AcceptChanges();
How to resolve this problem...How do I update my sql server database...by deleting a row from dataset..
I hope this will work for you:
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
SqlConnection con = new SqlConnection();
con.ConnectionString = cs;
SqlDataAdapter adpt = new SqlDataAdapter("Select * from RegisterInfoB", con);
DataSet ds = new DataSet();
adpt.Fill(ds, "RegisterTable");
foreach (DataRow dr in ds.Tables[0].Rows)
{
if (dr["FirstName"].ToString().Trim() == "praveen")
{
dr.Delete();
}
}
adpt.Update(ds);
Two Changes
1st: if (dr["FirstName"].ToString().Trim() == "praveen") trimming the blank spaces in your db's FirstName Field.
2nd : use adpt.Update(ds); to update your DB.
Another Way to doing it:
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
SqlConnection con = new SqlConnection();
con.ConnectionString = cs;
string firstName= "praveen"; // this data will get from calling method
SqlDataAdapter adpt = new SqlDataAdapter("Select * from RegisterInfoB", con);
DataSet ds = new DataSet();
adpt.Fill(ds, "RegisterTable");
string deleteQuery = string.Format("Delete from RegisterInfoB where FirstName = '{0}'", firstName);
SqlCommand cmd = new SqlCommand(deleteQuery, con);
adpt.DeleteCommand = cmd;
con.Open();
adpt.DeleteCommand.ExecuteNonQuery();
con.Close();
Similary, you can write query for UpdateCommand and InsertCommand to perform Update and Insert Respectively.
Find rows based on specific column value and delete:
DataRow[] foundRows;
foundRows = ds.Tables["RegisterTable"].Select("FirstName = 'praveen'");
foundRows.Delete();
EDIT: Adding a DeleteCommand to the data adapter (based on example from MSDN)
Note: Need an Id field here instead of FirstName, but I don't know your table structure for RegisterInfoB. Otherwise, we delete everyone named "praveen".
// Create the DeleteCommand.
command = new SqlCommand("DELETE FROM RegisterInfoB WHERE FirstName = #FirstName", con);
// Add the parameters for the DeleteCommand.
parameter = command.Parameters.Add("#FirstName", SqlDbType.NChar, 25, "FirstName");
parameter.SourceVersion = DataRowVersion.Original;
// Assign the DeleteCommand to the adapter
adpt.DeleteCommand = command;
To update a database with a dataset using a data adapter:
try
{
adpt.Update(ds.Tables["RegisterTable"]);
}
catch (Exception e)
{
// Error during Update, add code to locate error, reconcile
// and try to update again.
}
Sources: https://msdn.microsoft.com/en-us/library/xzb1zw3x(v=vs.120).aspx
https://msdn.microsoft.com/en-us/library/y06xa2h1(v=vs.120).aspx
hope that resolve the problem,
Try it:
var connectionString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
var selectQuery = "Select * from RegisterInfoB";
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand selectCommand = new SqlCommand(selectQuery, connection);
SqlDataAdapter adapter = new SqlDataAdapter(selectCommand);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
DataSet dataSet = new DataSet();
// you can use the builder to generate the DeleteCommand
adapter.DeleteCommand = builder.GetDeleteCommand();
// or
// adapter.DeleteCommand = new SqlCommand("DELETE FROM RegisterInfoB WHERE Id= #Id", connection);
adapter.Fill(dataSet, "RegisterInfoB");
// you can use the foreach loop
foreach (DataRow current in dataSet.Tables["RegisterInfoB"].Rows)
{
if (current["FirstName"].ToString().ToLower() == "praveen")
{
current.Delete();
}
}
// or the linq expression
// dataSet.Tables["RegisterInfoB"]
// .AsEnumerable()
// .Where(dr => dr["FirstName"].ToString().ToLower().Trim() == "praveen")
// .ToList()
// .ForEach((dr)=> dr.Delete());
var result = adapter.Update(dataSet.Tables["RegisterInfoB"]);
also you can add some events and put a breakpoint to see if the state is changing or if there is an error that prevent changes on the source:
dataSet.Tables["RegisterInfoB"].RowDeleted += (s, e) =>
{
var r = e.Row.RowState;
};
dataSet.Tables["RegisterInfoB"].RowDeleting += (s, e) =>
{
var r = e.Row.RowState;
};

Pass String into SQL Query from Textbox

Background
I've written a function that retrieves data using a SQL query and then outputs that data to a label. At the moment the search string is hard coded to "1002". The function is fired on a button click event.
Question
How do I pass data into my SQL query from a textbox so my search string is the contents of the text box, instead of 1002?
Code
private void getInfoStationID()
{
String ConnStr = "Data Source=SqlServer; Initial Catalog=Database; User ID=Username; Password=Password";
String SQL = "SELECT stationname FROM dbo.Stations WHERE StationID = 1002";
SqlDataAdapter Adpt = new SqlDataAdapter(SQL, ConnStr);
DataSet question = new DataSet();
Adpt.Fill(question);
foreach (DataRow dr in question.Tables[0].Rows)
{
nameTtb.Text += question.Tables[0].Rows[0]["stationname"].ToString();
}
}
Change the query to:
string constring = #""; // Declare your connection string here.
String SQL = "SELECT stationname FROM dbo.Stations WHERE StationID = #StationId";
SqlConnection con = new SqlConnection(constring);
con.Open();
SqlCommand command = new SqlCommand(SQL ,con);
and then you have to add parameter to the command object like this:
command .Parameters.Add("#StationId",SqlDbType.NVarChar).Value = textbox.Text;
Now you might be wondering why I have used parameters in the query. It is to avoid SQL Injection.
DataSet ds = new DataSet();
SqlDataAdapter adb = new SqlDataAdapter(command);
adb.Fill(ds);
con.Close();
And now you can iterate like this...
foreach (DataRow row in ds.Tables[0].Rows)
{
}
And you have to initialise the connection object and pass your connection string in it.
You can change your SQL string to use a variable, like #StationID, then add the variable to the query from textbox.text
String SQL = "SELECT stationname FROM dbo.Stations WHERE StationID = #StationID";
SqlCommand cmd = new SqlCommand;
cmd.CommandText = SQL;
cmd.CommandType = CommandType.Text;
cmd.Connection = ConnStr;
cmd.Parameters.AddWithValue("#StationID", Textbox1.Text);
da = new SqlDataAdapter(cmd);
DataSet nds = new DataSet();
da.Fill(nds);
String ConnStr = "Data Source=SqlServer; Initial Catalog=Database; User ID=Username; Password=Password";
string SQL = "SELECT stationname FROM dbo.Stations WHERE StationID = #stationID";
SqlCommand command = new SqlCommand(SQL, ConnStr);
command.Parameters.Add(new SqlParameter("#stationID", SqlDbType.Int));
command.Parameters["#stationID"].Value = textbox.Text;

How to pass dataset through query

I need to get a database values to the p_cat combo box .....but i cannot pass the dataset inside the query..
class Datatbl_Class1
{
DataSet ds = new DataSet();
public DataSet filldata(string q)
{
string myconnection = "datasource=localhost;port=3306;username = root; password = 12345V";
MySqlConnection con = new MySqlConnection(myconnection);
MySqlCommand cmd = new MySqlCommand(q, con);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(ds);
return ds;
}
}
Select_int_Class1 s4 = new Select_int_Class1();
string q = "SELECT Sup_ID FROM gtec_computer.supplier WHERE Sup_Name='" +p_cmb_sup.Text+ "'";
string ww = "Sup_ID";
int t = s4.select_val_int(q, ww);
DataSet n = new DataSet();
Datatbl_Class1 dt = new Datatbl_Class1();
string Query = "SELECT Cat_ID FROM gtec_computer.supplier_detail WHERE Sup_Id="+t+" ";
n = dt.filldata(Query)
DataSet ds = new DataSet();
string myconnection = "datasource=localhost;port=3306;username = root; password = 12345V";
MySqlConnection con = new MySqlConnection(myconnection);
string q1 = "SELECT cat_Name FROM gtec_computer.category WHERE Cat_ID= " + n + " ";
MySqlCommand cmd = new MySqlCommand(q1, con);
MySqlDataAdapter da1 = new MySqlDataAdapter(cmd);
da1.Fill(ds);
p_cat.DataSource = ds;
You should be able to via parameter to the function call in the class... However, by building your command strings, you would be wide open for SQL-injection. Look into parameterized queries. Now, back to your original code and an alternative implementation...
class Datatbl_Class1
{
public DataSet filldata(string q )
{
string myconnection = "datasource=localhost;port=3306;username = root; password = 12345V";
MySqlConnection con = new MySqlConnection(myconnection);
MySqlCommand cmd = new MySqlCommand(q, con);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataSet ReturnThisOne = new DataSet();
da.Fill(ReturnThisOne);
return ReturnThisOne;
}
}
Just dont make the "ds" as a property of the class. Just create a new instance of a dataset within your method. It will be a pointer anyhow. Fill that and return the pointer to the calling source as you already are doing with your "n = dt.filldata(Query)". Yes, the function is no longer using the data table, but since it's reference is being returned, then the "n" location that is calling it will retain it. It won't get released to garbage collection until the function that "n" is in gets released.
Again, look into parameters to prevent sql-injection. But this should get you going.

Prepared SELECT statement in .Net

I can't understand what I am doing wrong, I can't seem to SELECT with a prepared statement. However I can INSERT with a prepared statement.
MySqlCommand cmd = new MySqlCommand("SELECT * FROM code_post WHERE name = ?postRequired LIMIT 1", dbcon);
cmd.Parameters.Add(new MySqlParameter("?postRequired", requestString));
cmd.ExecuteNonQuery();
DataSet ds = new DataSet();
cmd.fill(ds, "result");
try {
thisBlog = ds.Tables["result"].Rows[0];
} catch {
invalid();
return;
}
Any advice on this would be greatly appreciated!
To fill a DataSet you will need a DataAdapter.
Try this:
MySqlCommand cmd = new MySqlCommand("SELECT * FROM code_post WHERE name = ?postRequired LIMIT 1", dbcon);
cmd.Parameters.Add(new MySqlParameter("?postRequired", requestString));
cmd.ExecuteNonQuery();
DataSet ds = new DataSet();
MySqlDataAdapter dAdap = new MySqlDataAdapter();
dAdap.SelectCommand = cmd;
dAdap.Fill(ds, "result");
try {
thisBlog = ds.Tables["result"].Rows[0];
} catch {
invalid();
return;
}
You need to use SqlDataAdapter
DataAdapter represents a set of data commands and a database connection that are used to fill the DataSet and update a SQL Server database.
The SqlDataAdapter provides this bridge by mapping Fill, which changes the data in the DataSet to match the data in the data source
Check the following syntax:
private static DataSet SelectRows(DataSet dataset,
string connectionString,string queryString)
{
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(
queryString, connection);
adapter.Fill(dataset);
return dataset;
}
}

Categories

Resources