C# insert foreign key that has same value with primary key - c#

How can I insert my FK_clubID from ClubMember table that references Clubs(clubID)?
I'm using the identity (1,1) on clubID should I add the value for FK_clubID?
public void addclubs(string clubname, DateTime established, byte[] images, string activate)
{
string insertSQL = "INSERT INTO Clubs(club_name,established,image,activate)" + "Values(#club,#esb,#img,#acv)";
Connect();
SqlCommand cmd = new SqlCommand(insertSQL, conn);
cmd.Parameters.AddWithValue("#club", clubname);
cmd.Parameters.AddWithValue("#esb", established);
cmd.Parameters.AddWithValue("#img", images);
cmd.Parameters.AddWithValue("#acv", activate);
cmd.ExecuteNonQuery();
return ;
}
public void addclubmember(string presidentID , string viceID, string secID, string president, string vice, string sec)
{
string updateSQL = "INSERT INTO ClubMember(presidentID,viceID,secID,president,vice,sec) VALUES (#prs,#vice,#sec,#prsn,#vicen,#secn)";
Connect();
SqlCommand cmd = new SqlCommand(updateSQL, conn);
cmd.Parameters.AddWithValue("#prs", presidentID);
cmd.Parameters.AddWithValue("#vice", viceID);
cmd.Parameters.AddWithValue("#sec", secID);
cmd.Parameters.AddWithValue("#prsn", president);
cmd.Parameters.AddWithValue("#vicen", vice);
cmd.Parameters.AddWithValue("#secn", sec);
cmd.ExecuteNonQuery();
return;
}

You need to change the first method to return the ClubID just inserted
public int addclubs(string clubname, DateTime established, byte[] images, string activate)
{
string insertSQL = #"INSERT INTO Clubs(club_name,established,image,activate)
Values(#club,#esb,#img,#acv);
SELECT SCOPE_IDENTITY()";
Connect();
SqlCommand cmd = new SqlCommand(insertSQL, conn);
cmd.Parameters.AddWithValue("#club", clubname);
cmd.Parameters.AddWithValue("#esb", established);
cmd.Parameters.AddWithValue("#img", images);
cmd.Parameters.AddWithValue("#acv", activate);
int newClubID = cmd.ExecuteScalar();
return newClubID;
}
In this way you get back the last identity value inserted using your connection instance. Of course you could add it to your query that updates the members of that club changing the current query to add also this parameter for its column.
Beware that the last inserted identity in your connection could be different if there is a trigger on the club table that inserts data in other tables with identity columns
Unrelated to your current problem I have also two other advices to your code. First, try to use objects to represent Clubs and ClubMembers, it is not clear if you have just a bunch of simple variables here or if you have a more structured way to represent your data models. Second, do not use AddWithValue. This is handy but has many drawbacks both in terms of performances and in terms of reliability. See AddWithValue is Evil

Assuming you have a column in your database table of "ClubMember" named "clubID" which has a foreign key constraint with primary key from "Club" table, this is how you insert the value:
public void addclubmember(string presidentID , string viceID, string secID,
string president, string vice, string sec, string clubID)
{
string updateSQL = "INSERT INTO
ClubMember(presidentID,viceID,secID,president,vice,sec, clubID) VALUES
(#prs,#vice,#sec,#prsn,#vicen,#secn, #clubID)";
Connect();
SqlCommand cmd = new SqlCommand(updateSQL, conn);
cmd.Parameters.AddWithValue("#prs", presidentID);
cmd.Parameters.AddWithValue("#vice", viceID);
cmd.Parameters.AddWithValue("#sec", secID);
cmd.Parameters.AddWithValue("#prsn", president);
cmd.Parameters.AddWithValue("#vicen", vice);
cmd.Parameters.AddWithValue("#secn", sec);
cmd.Parameters.AddWithValue("#clubID", clubID);
cmd.ExecuteNonQuery();
}

Related

How to send properties with SQL in C#

I have two classes, first name is class 1 to collect your name and family addition to your car. This came from another class that name is car.
This class (car) has two properties, actually I won't get information directly.
For these classes we have two tables as well - first table has relation with class 1, name is qqq and car connected with car.
What's the problem?
In qqq table I have column id_car. When the customer registers himself, his car id should be stored into the qqq table.
I don't know how pass properties with SQL command
Server code:
public class Class1
{
public int id { get; set; }
public string name { get; set; }
public string family { get; set; }
public car car_id { get; set; }
}
public class car
{
public int id { get; set; }
public String name { get; set; }
public String color { get; set; }
}
Client-side code:
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlcon;
sqlCommand.CommandText = "insert into cars (name , color) values('BMW','gray');";
sqlCommand.ExecuteNonQuery();
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name, family, id_car) values (#name, #family, #car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", "***MAIN PROBLEM***");
sqlCommand1.ExecuteNonQuery();
The answer is in the code below. There are also several things here that should be improved, which I will call out via the comments:
//You can put several statements in one sql string.
string sql = "
declare #car int;
insert into cars (name , color) values('BMW','gray');
set #car = scope_identity();
insert into qqq (name, family ,id_car) values (#name,#family,#car);";
// Create a new connection object for each call to the database. Really.
// Read this for more info why: https://softwareengineering.stackexchange.com/q/142065/8057
using (var sqlcon = new SqlConnection("connection string here"))
using (var command = new SqlCommand(sql, sqlcon))
{
//AddWithValue can cause certain serious performance problems
// Instead, be specific about the database type and length for the target column.
// I have to guess here, but you can find this info in your database
command.Parameters.Add("#name", SqlDbType.NVarChar, 50).Value = textBox1.Text;
command.Parameters.Add("#family", SqlDbtype.NVarChar, 120).Value = textBox2.Text;
sqlcon.Open();
command.ExecuteNonQuery();
} // The connection will be closed and disposed here, even if an exception is thrown.
// Your original code would have left the connection open if there was an exception.
If you want to be really careful, you'll also add a transaction to that SQL. This way if the second part fails the first part can be rolled back and you don't end up accidentally only doing part of the work.
If you still want the new id_car value for later use in your application, you can further add a select #car; to the end of the SQL string and change ExecuteNonQuery() to ExecuteScalar() to get the value back.
First at all, you can get the last ID if it is a Identity ID (AUTO_INCREMENT) after insert to the table Car. Then past this ID to the qqq table.
Example:
// for MySQL
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') OUTPUT INSERTED.ID VALUES(#UserId, #GameId)";
Int32 newId = (Int32) sqlCommand.ExecuteScalar();
// for SQL Server
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') VALUES(#UserId, #GameId); SELECT SCOPE_IDENTITY();";
int primaryKey = Convert.ToInt32(sqlCommand.ExecuteScalar());
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name , family ,id_car) values (#name,#family,#car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", newId); // mysql
sqlCommand1.Parameters.AddWithValue("#car", primaryKey); // sql server

Update Set command works in Access but not in Visual Studio with #parameters

I have been working on a personal project for the company I work for to control stock levels in order to practice my c#.
I want my application to search through tblJuiceStock, find a matching FlavourID to what the user is inputting and update the stock of that record through an UPDATE SET query.
public void InsertJuiceStockWithCheck()
{
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = ConnectionString;
conn.Open();
string tblJuiceStockCheck = "SELECT FlavourID, Quantity FROM tblJuiceStock";
OleDbCommand cmdCheck = new OleDbCommand(tblJuiceStockCheck, conn);
OleDbDataAdapter daCheck = new OleDbDataAdapter(cmdCheck);
DataTable dtCheck = new DataTable();
daCheck.Fill(dtCheck);
foreach (DataRow row in dtCheck.Rows)
{
if ((int)row["FlavourID"] == fID)
{
int currentQty = (int)row["Quantity"];
int updatedQty = currentQty + qty;
string tblJuiceStockExisting = #"UPDATE tblJuiceStock
SET Quantity = #newquantity
WHERE FlavourID = #flavourID";
OleDbCommand cmdJuiceStockExisting = new OleDbCommand(tblJuiceStockExisting, conn);
cmdJuiceStockExisting.Parameters.AddWithValue("#flavourID", fID);
cmdJuiceStockExisting.Parameters.AddWithValue("#newquantity", updatedQty);
cmdJuiceStockExisting.ExecuteNonQuery();
matchFound = true;
break;
}
}
if (!matchFound)
{
string tblJuiceStockNew = "INSERT INTO tblJuiceStock (FlavourID, Quantity, MinStockPOS) VALUES (#fID, #quantity, #minstock)";
OleDbCommand cmdJuiceStockNew = new OleDbCommand(tblJuiceStockNew, conn);
cmdJuiceStockNew.Parameters.AddWithValue("#fID", fID);
cmdJuiceStockNew.Parameters.AddWithValue("#quantity", qty);
cmdJuiceStockNew.Parameters.AddWithValue("#minstock", amt);
cmdJuiceStockNew.ExecuteNonQuery();
}
}
}
Please note: this query works fine in Access when I replace parameters with the same values. Also, using breakpoints I identified that the parameters have the correct values set to them, the variables assigned to them are obtained within another method, all methods are called in the submit button event.
However, the Quantity value in TblJuiceStock remains the same.
My tblJuiceStock table
After some time of messing about the answer was simple.
OLEDB does work with named parameters but you have to declare them, if you don't declare them they use the parameters positioning to match them up.
My problem was that in my query string I had #newquantity first and #flavourID second, whereas when adding my parameters I added #flavourID first and #newquantity second.

Parsing varchar as int for inserting values into the database

I have to add 4 values into my table:#SNTeacher,#name,#pwd and #courseID.The #courseID is a FK in my RegisterTeacher table and a PK I Courses table along with another attribute-#coursename.
My problem is that when I want to insert the values into the table, I get an error at #courseID saying that it can't convert from varchar to int although my #courseID is an int.
My #courseID and #coursename are binded to comboBoxcourse1 and it has DisplayMember-coursename and ValueMember=courseID.My opinion is that it makes the confusion between the two of them since #coursename is a varchar, but then again I don't see the logic since I'm adding the #courseID parameter to the table RegisterTeacher.
I also tried to parse it in 3 different ways that I have also found here, on Stack Overflow but still I get errors saying that the input string was not in a correct format.
This is my code with the error and in is also the last method I used to try to parse the value:
private void btnRegister_Click(object sender, EventArgs e)
{
string connString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\User\source\repos\VIAUniversityCollegeAttendanceApp\VIAUniversityCollegeAttendanceApp\DatabaseAttendanceStudents.mdf;Integrated Security=True;Connect Timeout=30";
SqlConnection con = new SqlConnection(connString);
con.Open();
SqlCommand cmd = new SqlCommand("Insert into RegisterTeacher values(#SNTeacher,#name,#pwd,#courseID) ", con);
cmd.Parameters.AddWithValue("#SNTeacher", textBoxSN.Text);
cmd.Parameters.AddWithValue("#name",textBoxName.Text);
cmd.Parameters.AddWithValue("#pwd", textBoxpwd.Text);
string nvarchar = "#courseID";
var one = int.Parse(nvarchar);
var bone = int.TryParse(nvarchar, out one);
cmd.Parameters.AddWithValue("#courseID", comboBoxcourse1.Text);
cmd.ExecuteNonQuery();
MessageBox.Show("Registration succesfull!");
}
This should work for you:
int parameterValue;
SqlParameter parameter = new SqlParameter("#courseID", SqlDbType.Int);
if(Int32.TryParse(comboBoxcourse1.SelectedValue?.ToString() ?? String.Empty, out parameterValue))
{
parameter.Value = parameterValue;
}
else
{
parameter.Value = DBNull.Value;
}
cmd.Parameters.Add(parameter);

How can i retrive all grdiview columns values in one iteration without loop?

I'm facing problem in creating table programtically in asp.net c#. I'm working on sql project. I have a gridview and a button,When I click on button then I want that all gridview columns values e.g column_name,data type,allowNull,PrimaryKey etc.
All values inserted inside the "Create Table QUERY" in one iteration and table will be created, But I have a problem. I'm using for loop when loop first time execute then only one row iterate and table created in SQL only one column(Just first row) and when 2nd iteration execute then table name will be same ,so there is a issue.
Kindly tell me how can I resolve this issue.All values successfully inserted into the table but problem is in creating table. Table is created but 'ONLY LAST ' row table is created,Table contain only one row.How can i resolve this issue.
How can i do this?
Here is my "button" code aspx.cs`
public void insert(object sender, EventArgs e)
{
SqlConnection cnn = new SqlConnection("Data Source=HAMEED_KHAN\\SQLEXPRESS;Initial Catalog=db_compiler;Integrated Security=True");
string d=Session["value"].ToString();
SqlCommand cmd2=new SqlCommand("SELECT Database_id FROM Create_db WHERE Database_Name='"+d+"'",cnn);
cnn.Open();
string dbid = cmd2.ExecuteScalar().ToString();
cnn.Close();
int D_ID = Int32.Parse(dbid);
string str = "";
string type = "";
for (int i = 0; i < GridView2.Rows.Count; i++)
{
string tblname = "abc";
str=GridView2.Rows[i].Cells[1].Text.ToString();
type=GridView2.Rows[i].Cells[2].Text.ToString();
string Name = GridView2.Rows[i].Cells[1].Text.ToString();
string Type = GridView2.Rows[i].Cells[2].Text.ToString();
CheckBox allow=GridView2.Rows[i].Cells[3].Controls[0]as CheckBox;
CheckBox primary = GridView2.Rows[i].Cells[4].Controls[0] as CheckBox;
string s = Session["UID"].ToString();
int id = Int32.Parse(s);
string date = DateTime.Now.ToString();
string A = (allow.Checked == true ? "NULL" : "NOT NULL");
string P = (primary.Checked == true ? "PRIMARY KEY" : "");
// string query="USE "+d+" CREATE TABLE ABCD ("+Name+" "+Type+" "+A+")";
// SqlCommand cmd3 = new SqlCommand(query, cnn);
SqlCommand cmd = new SqlCommand("insertTbl", cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", tblname);
cmd.Parameters.AddWithValue("#col_name", Name);
cmd.Parameters.AddWithValue("#dtype",Type);
cmd.Parameters.AddWithValue("#dbId", D_ID);
cmd.Parameters.AddWithValue("#allow",(allow.Checked==true ? "true" : "false"));
cmd.Parameters.AddWithValue("#primary", (primary.Checked == true ? "true" : "false"));
cmd.Parameters.AddWithValue("#user", id);
cmd.Parameters.AddWithValue("#date", date);
SqlDataAdapter ad = new SqlDataAdapter(cmd);
cnn.Open();
cmd.ExecuteNonQuery();
// cmd3.ExecuteNonQuery();
cnn.Close();
}
string str1=str;
string str2=type;
//string AA="ALLOW NULL";
// string queryy =string.Format(#"USE {"+d+"}; IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE NAME = 'ABCDE'))CREATE TABLE ABCDE ({"+str1+"} {"+type+"} {"+AA+"})");
string queryy="USE "+d+" If not exists (select name from sysobjects where name = 'Customers') CREATE TABLE Customers("+str1+" "+type+")";
SqlCommand cmd4 = new SqlCommand(queryy, cnn);
cnn.Open();
cmd4.ExecuteNonQuery();
cnn.Close();
}
You should make sure to avoid recreating the same table by using a rerunnable script. For CREATE TABLE, checking its existence is done this way:
string query = String.Format(#"
USE {0};
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = '{1}'))
CREATE TABLE {1} ({2} {3} {4})", d, "ABCD", Name, Type, A);
Notice that I have used String.Format to increase readability and avoid string concatenation (strings are immutable, so many instances are created when using + operator).
However, consider moving your CREATE TABLE outside of for loop, if your intention is to create once and insert multiple times. Anyway, existence check should be performed.
From C# 6.0, you can use both verbatim and interpolation (actually, string interpolation was introduced in 6.0). Something like this:
string query = $#"
USE {d};
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'ABCD'))
CREATE TABLE ABCD ({Name} {Type} {A})";

Update Statement into Textboxes c# data type mismatched in criteria

Attempting to use the update Statement but when I execute the program it claims:
user type mismatch in data criteria
When I click the updatebutton, I want for the database to update where ID =
private void Update_Click(object sender, EventArgs e)
{
//OPENING CONNECTION
db.Open();
int idd = int.Parse( InstructorIDText.Text);
OleDbCommand df = new OleDbCommand("UPDATE Instructors SET FirstName='"+FNText.Text+"',LastName='"+Lntext.Text+"',Street='"+StreetText.Text+"',City='"+CityText.Text+"',State='"+StateText.Text+"',Zip='"+ZipText.Text+"',Office='"+OfficeText.Text+"',EMail='"+EmailText.Text+"' WHERE ID = " + idd +"", db);
//creating parameters
df.Parameters.AddWithValue("#ID", InstructorIDText.Text);
df.Parameters.AddWithValue("#FirstName", FNText.Text);
df.Parameters.AddWithValue("#LastName", Lntext.Text);
df.Parameters.AddWithValue("#Street", StreetText.Text);
df.Parameters.AddWithValue("#City", CityText.Text);
df.Parameters.AddWithValue("#State", StateText.Text);
df.Parameters.AddWithValue("#Zip", ZipText.Text);
df.Parameters.AddWithValue("#Office", OfficeText.Text);
df.Parameters.AddWithValue("#EMail", EmailText.Text);
df.ExecuteNonQuery();
db.Close();
}
Use #parameter in query instead of concatenating exact values
For MS-SQL
//OPENING CONNECTION
db.Open();
int idd = int.Parse(InstructorIDText.Text);
OleDbCommand df = new OleDbCommand("UPDATE Instructors SET FirstName=#FirstName,LastName=#LastName,Street=#Street,City=#City,State=#State,Zip=#Zip,Office=#Office,EMail=#EMail WHERE ID = #ID", db);
//creating parameters
df.Parameters.AddWithValue("#ID", InstructorIDText.Text);
df.Parameters.AddWithValue("#FirstName", FNText.Text);
df.Parameters.AddWithValue("#LastName", Lntext.Text);
df.Parameters.AddWithValue("#Street", StreetText.Text);
df.Parameters.AddWithValue("#City", CityText.Text);
df.Parameters.AddWithValue("#State", StateText.Text);
df.Parameters.AddWithValue("#Zip", ZipText.Text);
df.Parameters.AddWithValue("#Office", OfficeText.Text);
df.Parameters.AddWithValue("#EMail", EmailText.Text);
df.ExecuteNonQuery();
db.Close();
When using add with value use the variable idd instead of the .Text property. The query is expecting an int for your #id parameter but you are supplying a string.
See if that helps

Categories