How to add to an Update statement - c#

I am trying to update my database(Table) and make the active column = 1.
I have duplicate reports (subject_text) with different countries and parameters.
subject_text countries parameter1 active
usage GB 1 0
usage FR 2 0
usage PT 1 0
closed GB,FR,PT 1 0
Here is an example of what my database looks like(simplified, there are many more parameters and many more reports but i hope you can see what I mean by duplicate report names)
Here is my .cs file to show the update i am trying to carry out.The Subject_text are in drop-down list form so the user can select which report to update. These reports(subject_text) are hard-coded into my ASPX page. When selecting a report such as 'closed' the update works, but when it comes to updating reports which have different countries or parameters that where i'm having trouble.
Masterpage masteris linking this page to where the .getDropDownListValue is
How can I add to my update statement when the drop-down lists contain different elements?
protected void RunReport_Click (object sender, System.EventArgs e)
{
MasterPage master = (MasterPage)this.Master;
string sqlStatement = "";
sqlStatement = #"UPDATE [TODD].[dbo].[Table] SET Active='1' WHERE subject_text = #report";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sqlStatement, conn);
cmd = new SqlCommand(sqlStatement, conn);
cmd.Parameters.AddWithValue("#report", ddl_Report.SelectedItem.Text);
string getcountry = master.getDropDownListValue(ddl_country, false);
if (!string.IsNullOrWhiteSpace(getcountry))
{
cmd.Parameters.AddWithValue("#country", getcountry);
sqlStatement += "AND countries = #country";
}
string getparam1 = master.getDropDownListValue(Param1, false);
if (!string.IsNullOrWhiteSpace(getparam1))
{
cmd.Parameters.AddWithValue("#param1", getparam1);
sqlStatement += "AND parameter1 = #param1";
}
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
Thank you for your time.

move
SqlCommand cmd = new SqlCommand(sqlStatement, conn);
to below the final calculation of your string sqlStatement
adding new text to sqlStatement should be done before you create your SqlCommand based on sqlStatement
also, you do not need to call new SqlCommand(sqlStatement, conn); twice

Why don't you just pass the identity? This is much cleaner.
UPDATE [TODD].[dbo].[Table] SET Active='1' WHERE RecordID = #RecordId

Related

Is there a way that I can send values to database while using multiple textboxes?

I'm creating a reservation system and this is my forms, I'm having a hard time trying to send the quantity of the products because I'm using multiple textboxes unlike the reservation id I can easily get the value because I'm only using one textbox
SqlConnection con = new SqlConnection(#"Data Source = MAAAYYK; Initial Catalog = dbFoodReservation; Integrated Security = True");
SqlCommand cm = new SqlCommand();
con.Open();
cm = new SqlCommand("Insert into tbl_Reservation(ReservationID,ReceiptID,Price,Qty)Values(#ReservationID, #ReceiptID, #Price, #Qty)", con);
cm.Parameters.AddWithValue("#ReservationID", txtBoxreserveID.Text);
cm.Parameters.AddWithValue("#ReceiptID", txtboxReceiptID.Text);
cm.Parameters.AddWithValue("#Price", txtboxTotal.Text);
cm.Parameters.AddWithValue("#Qty", txtfried.Text + txtbbq.Text);
cm.ExecuteNonQuery();
con.Close();
the blank one is there I don't know what to put because as you can see I'm in my form there are many textbox for the quantity
Is there a way for me to get those values like if loop or something?
I changed my code and found a way to send the value of qty but when I enter 1 and 1 it shows 11 in the database instead of 2
Here is the database
You must convert text to Integer for Prevent concatenate strings.
// clean code
var intTxtfried = Convert.ToInt32(txtfried.Text);
var intTxtbbq = Convert.ToInt32(txtbbq.Text);
var totalQty = intTxtfried + intTxtbbq;
// other code ...
cm.Parameters.AddWithValue("#Qty", totalQty);

How do I add data from ListBox into SQL Server database in C# Windows forms?

I am working on a project where the user gets to generate a set of licenses keys and export it into a text file. The information is then displayed in a listbox as shown below. I am using C# and Windows Forms:
On top of this I would also like to save the details from the listbox into the local SQL Server database for record keeping purposes in my application. I have tried out various methods I found online to do this but all were unsuccessful.
One of the methods I've found is from this link:
https://www.youtube.com/watch?v=hUZGyA6UKGI&t=0s&index=26&list=PLZEMJ7iJtVdq9aMAiDfRlMoNrzGaWOfkZ
Here is the code I used from the video tutorial:
private void recordinserted(List<string>li)
{
StringBuilder stringbi = new StringBuilder(string.Empty);
foreach (string item in li)
{
const string qry = "Insert into [LicenseDB](Comapny Name, Software Name, LicenseKeys)values";
stringbi.AppendFormat("{0}('{i}');",qry,item);
}
SqlConnection con = new SqlConnection();
con.ConnectionString = (#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\User\Documents\Database.mdf;Integrated Security=True;Connect Timeout=30");
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = stringbi.ToString();
cmd.Connection = con;
int a = cmd.ExecuteNonQuery();
if (a > 0)
{
MessageBox.Show("inserted");
}
}
// adding into local database (method placed in button click)
List<string> li = new List<string>();
foreach (ListViewItem item in lbGeneratedKeys.Items)
{
if (item.Selected)
{
li.Add(item.Text);
}
recordinserted(li);
}
I realized that the person was using C# with ASP.Net and makes use of ListITem property which Windows Form does not have.
The other method I used is the classic SqlConnection method:
//adding into local database
using (SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\User\Documents\Database.mdf;Integrated Security=True;Connect Timeout=30"))
{
con.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO LicenseDB (Company Name, Software Name, LicenseKeys,LicenseFileNo) VALUES (#cName, #sName, #lKeys, #lno)");
cmd.CommandType = CommandType.Text;
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
lbGeneratedKeys.Items.Add(dr[0].ToString());
lbGeneratedKeys.Items.Add(dr[1].ToString());
lbGeneratedKeys.Items.Add(dr[2].ToString());
lbGeneratedKeys.Items.Add(dr[3].ToString());
}
}
I used (dr[0].ToString()) to read each line from the listbox to be added into the database, where each number represents a row in the listbox. Eg. [0] represents the company name in the listbox. However when I try to execute the program there's an error saying that the SqlDataReader row is not initialized.
Also, since my program has the algorithm for users to generate more than one license keys, I also need help on how I can group these several rows of generated license keys to be added into one database column in the Database table. For instance in my UI above, I chose to generate 3 license keys and each license key takes up a row in the ListBox, I would like to group these three rows together to be placed under one database column variable (licenseKeys). I would like the algorithm to be able to read the generated keys dynamically as well as the user can generate as many license keys as needed.
I hope I had understood your problem:
First of all, I think is very important to define your data model. For example, in order to allow that a user can define a lot of keys, I would use another table where all the keys were stored, after that you need to define if a same key could be related to more than one row on the table 'LicenseDB' (in the table 'LicenseDB' you would have the columns Company Name, Software Name, LicenseFileNo). If so you'd have the relation (n:n) and then you would need to build another intermediate table that defines the relation between the table 'keys' and the table 'LicenseDB' . If it's not the case, then you simple define the relation between 'keys' and 'LicenseDB' (n:1) adding a column licenseDbID to the table 'keys' that relation many keys to one row in the table 'LicenseDB'
On the other hand, the problem with your code is that you are trying to insert data and not to read data, so you don't need a DataReader instead of that you just simply could implement something like this:
using (SqlConnection con = new SqlConnection('YOUR STRING CONNECTION'))
{
con.Open();
string comando = "INSERT INTO LicenseDB (companie, software) VALUES ('" + lbGeneratedKeys.Items[0].ToString() + "','" + lbGeneratedKeys.Items[1].ToString() + "')";
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = comando;
cmd.Connection = con;
cmd.ExecuteNonQuery();
}
In this case, two values are inserted into the table LicenseDB the values for companie name and software name.
I hope I had helped you.
I referred back to my previous school project and managed to save my listbox data into the SQL database. I have two listboxes in total: 1 for allowing user to export as text file, and the second to specifically store generated license keys only. The second listbox is set to not visible in my program.
The codes I used:
private void exportKey_Click(object sender, EventArgs e)
{
//adding into local database
//excludes adding licensekeys
SqlConnection sqlCon = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\User\Documents\Database.mdf;Integrated Security=True;Connect Timeout=30");
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand("addLicensedata", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue(#"companyName", companyTextbox.Text.Trim());
sqlCmd.Parameters.AddWithValue(#"softwareName", softwareTextbox.Text.Trim());
sqlCmd.Parameters.AddWithValue(#"prodID", prodidTextbox.Text.Trim());
sqlCmd.Parameters.AddWithValue(#"licenseType", cbLicensetype.Text.Trim());
sqlCmd.Parameters.AddWithValue(#"LicenseNo", licensekeyNum.Text.Trim()); //no of license keys
sqlCmd.ExecuteNonQuery();
//MessageBox.Show("Added to database");
sqlCon.Close();
if (cbLicensetype.SelectedItem.ToString() == "Trial")
{
sqlCmd.Parameters.AddWithValue(#"TrialDays", tbTrialdays.Text.Trim());
}
addtoFKtable();
private void addtoFKtable()
{
SqlConnection Con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\User\Documents\Database.mdf;Integrated Security=True;Connect Timeout=30");
Con.Open();
SqlCommand Cmd = new SqlCommand("addLicensekeys", Con);
Cmd.CommandType = CommandType.StoredProcedure;
Cmd.Parameters.AddWithValue(#"LicenseNo", licensekeyNum.Text.Trim());
Cmd.Parameters.AddWithValue(#"LicenseKeys", lbHidden.Text.Trim());
Cmd.Parameters.AddWithValue(#"prodID", prodidTextbox.Text.Trim());
Cmd.Parameters.AddWithValue(#"companyName", companyTextbox.Text.Trim());
Cmd.ExecuteNonQuery();
//MessageBox.Show("Added license to database");
Con.Close();
}
I stored my SQL commands as a stored procedure within the database, and just called the command in my codes.

How can i create a customizable SQL function in Visual Studio

Is it possible to create an extendable SQL query in Visual studio?
private void button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select geneID from Table3 where geneID in(" + filterdata + ")";
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
dataGridView1.DataSource = dt;
con.Close();
}
Can this be extended to select any possible parameter from any possible tables using any possible conditions. I think it would look something like the following:
Select [Variable 1,Variable 2...] from [Table 1, Table2...] where [Condition1, Condition 2...]
The variables, tables and conditions in this case will be selected using a multitude of checkbox's. I want to incorporate any possible search into one button click.
Use sql joins ..Inside your commenttext like select a.row,b.rowtwo from tableone a inner join tabletwo b on a.row = b.row where a.row = your values
You can use the String.Format method
Converts the value of objects to strings based on the formats specified and inserts them into another string.
If you are new to the String.Format method, see the Getting started with the String.Format method section for a quick overview.
So you can use like that
cmd.CommandText = String.Format("Select {0} from {1} where {2}", columns, tables, conditions)

Issues with Increment MS-SQL, C#

I am having an issue with the increment for the ID. The ID would increase by one every time I click insert, but the problem occurs when the ID 2, it would insert the values twice, if ID 3, it would insert the values three times, and so on.
There are couple of options that I have been trying. One is Max and the other one is finding the last inserted value and add one to the ID just.
I would appreciate if anyone can help me out with this. Thanks
public partial class LoginInfo : System.Web.UI.Page
{
static string myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
private void GenerateID()
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery1 = "Select Count(S_ID) from Student_Name";
SqlCommand cmd = new SqlCommand(myQuery1, myConnection);
myConnection.Open();
int addOneS_ID_Table1 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneS_ID_Table1++;
lblstdID.Text = addOneS_ID_Table1.ToString();
myConnection.Open();
cmd.CommandText = "Select Count(P_ID) from Student_Pass";
int addOneP_ID_Table2 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneP_ID_Table2++;
lblstdPass.Text = addOneP_ID_Table2.ToString();
/*-----------------------------------------------------------------*/
//SqlConnection myConnection = new SqlConnection(myConnectionString);
//SqlCommand cmd = new SqlCommand("SELECT MAX(S_ID) as max_S_ID from Student_Name",myConnection);
//cmd.CommandType = CommandType.Text;
//myConnection.Open();
//lblstdID.Text = Convert.ToString(cmd.ExecuteScalar());
//cmd.CommandText = "SELECT MAX(P_ID) as max_P_ID FROM Student_Pass";
//lblstdPass.Text = Convert.ToString(cmd.ExecuteScalar());
//myConnection.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
GenerateID();
}
}
protected void btnInsert_Click(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery = "Insert into Student_Name(S_ID,STUDENT_NAME) VALUES" + "(#S_ID,#STUDENT_NAME)";
SqlCommand cmd = new SqlCommand(myQuery,myConnection);
cmd.Parameters.Add("#S_ID", SqlDbType.Int).Value = lblstdID.Text;
cmd.Parameters.Add("#STUDENT_NAME", SqlDbType.VarChar).Value = txtstdName.Text;
if(myConnection.State == ConnectionState.Closed)
{
myConnection.Open();
}
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
//Second Table
cmd.CommandText = "Insert into Student_Pass(P_ID,PASSWORD) VALUES" + "(#P_ID,#PASSWORD)";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#P_ID", SqlDbType.Int).Value = lblstdPass.Text;
cmd.Parameters.Add("#PASSWORD", SqlDbType.VarChar).Value = txtStdPass.Text;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
myConnection.Close();
GenerateID();
lblResult.Text = "Successfully Saved";
GridView1.DataBind();
}
}
Problem is with your query since you are getting COUNT(S_ID) which is going to get you count of records doesn't necessarily will give exact ID number. You should rather try MAX(S_ID) or ORDER BY clause saying
Select MAX(S_ID) from Student_Name
(OR)
Select TOP 1 S_ID from Student_Name ORDER BY S_ID DESC;
But recommended, You should actually go with SQL Server ##IDENTITY or SCOPE_IDENTITY() to get the last inserted record ID (assuming that S_ID is an IDENTITY column)
It's highly recommended to not use max or top in order to determine the "next" identifier to use, simply because of the cost associated with it.
However, there are some other pitfalls to using max and top especially if there is a chance that nolock is used (which is a whole other conversation). I've seen a lot of web applications use max and has proven to be a performance killer.
Rahul is right, ##identity or scope_identity are good alternatives. However, I think this calls for using a native SQL Server sequence, which was introduced in SQL Server 2012. It was something that application developers have been waiting for and Microsoft finally delivered.
The issue with using ##identity or scope_identity is that you actually have to write rows to some table before you can even contemplate doing something.
This makes it a bit more costly and messier than what it may need to be. In the case of using a sequence, you can issue a new sequence number and then decide what to do and once you decide what to do you're still guaranteed that you're the only one with that sequence number.
You would create a sequence like this. You should check out the documentation as well.
create sequence dbo.StudentIdSeq
as int -- this can be any integer type
start with 1 -- you can start with any valid number in the int, even negative
increment by 1;
go
Then you issue new sequence numbers by doing this ...
select next value for StudentIdSeq;
It may still be good to create a stored procedure with an output parameter that you can call from C# (which is what I would do). In fact you may want to take it a step further, in the case that you have a bunch of sequences, and create a slick stored procedure that will get a new sequence based on the type that is being requested from the caller.

C# No value given for 1 or more required parameters, but I can't see why

I have posted the code I have below
I am trying to get the data from an Access 2002-2003 database
If I take out everything after the WHERE clause and just use "SELECT * FROM [{0}] then it takes all the data from the table with no problems. I have double checked the field names, they are definitely correct. I have more than 1 table with the same field names, so I thought maybe I would need to include the table name before the field name, but with or without the table I still get the same exception. I have tried moving the position of the square brackets, again with no success...
Even if I include only one of the WHERE clauses, the code no longer works, and I can't for the life of me work out why.. I have spent hours looking at numerous posts here and on other sites related to this error, but none of the suggestions have helped me..
The Destination field is a 'memo' field in Access.
The Next Collection fields are date fields, GVars.currentDate is set earlier in the code to be today's date (with the time portion set to 00:00:00).
GVars.thisFY is also set programatically as a string prior to this.
Any tips would be appreciated.
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE {0}.[Destination] = #Destination AND {0}.[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
// Add values to the fields
cmd.Parameters.AddWithValue("#Destination", "Henwood");
cmd.Parameters.AddWithValue("#NextCollectionA", GVars.currentDate);
cmd.Parameters.AddWithValue("#NextCollectionB", GVars.currentDate.AddDays(1));
adapter = new OleDbDataAdapter(cmd.CommandText, conn);
System.Diagnostics.Debug.Print(cmd.CommandText);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
catch (Exception ex)
{
}
EDIT:
Thanks Vladislav for the answer, corrected code posted below:
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE [{0}].[Destination] = #Destination AND [{0}].[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
cmd.Connection = conn;
// Add values to the fields
cmd.Parameters.Add("#Destination", OleDbType.Char).Value = "Henwood";
cmd.Parameters.Add("#NextCollectionA", OleDbType.DBDate).Value = GVars.currentDate;
cmd.Parameters.Add("#NextCollectionB", OleDbType.DBDate).Value = GVars.currentDate.AddDays(1);
adapter = new OleDbDataAdapter(cmd);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
Try to specify types for the parameters you add.
Another thing I notice is that to your adapter you are passing only the CommandText.
You should pass the whole command object.

Categories

Resources