Parsing varchar as int for inserting values into the database - c#

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);

Related

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

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();
}

C# is returning exception: Procedure has no parameters and arguments were supplied

I apologise for this formatting. I am new to programming and new to this site, so I will try and make the question as clear as possible.
I have a webform for accessing/modifying a Customer database. I have a button for entering new customers details which will automatically assign an ID number by getting the highest ID number from the database, and incrementing by one (and posting to form textbox).
This is the code I have written:
protected void btnNew_Click(object sender, EventArgs e)
{
Clear();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "NewCustomer";
conn.Open();
SqlParameter maxid = new SqlParameter();
maxid.ParameterName = "#MaxID";
maxid.SqlDbType = SqlDbType.Int;
maxid.Direction = ParameterDirection.Output;
command.Parameters.Add(maxid);
command.ExecuteNonQuery();
NewCustId = Convert.ToInt32(maxid.Value);
NewCustId += 1;
txtCustID.Text = (NewCustId).ToString();
txtCustID.DataBind();
conn.Close();
}
This is the stored procedure:
CREATE PROCEDURE NewCustomer
(#MaxID INT OUTPUT)
AS
BEGIN
SELECT #MaxID = MAX(CustID)
FROM dbo.Customer
END
I have tried many different ways of coding it, but nothing seems to work.
The code I have posted has an exception at ExecuteNonQuery saying arguments were supplied and procedure has no parameters. When I place command.Parameters.Add(maxid); underneath ExecuteNonQuery, it returns a 1.
I ran the SQL Query alone to see what would happen and it returns a correct answer in an unnamed cell. For some reason the Column Name disappears when it comes up. Then when I try to use the C# code to access the unnamed cell, I can't seem to access it because the column 'CustID' "doesn't exist".
With this code, I know that the SQL command is executing, and then the C# code increments by 1, but it seems that the return value I am getting is 0.
I appreciated any ideas that I can get on how to fix this. Thank you.
Edit: I have also tried:
DataTable table = new DataTable();
adapter.Fill(table);
NewCustId = table.Rows[0].Field("CustID");
(This is where it said 'CustID' column didn't exist)
Change your code to the following and try again:
Clear();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "NewCustomer";
conn.Open();
NewCustId = Convert.ToInt32(cmd.ExecuteScalar().ToString());
NewCustId += 1;
txtCustID.Text = NewCustId.ToString();
conn.Close();
And your stored procedure is:
CREATE PROCEDURE NewCustomer
(
)
AS
BEGIN
SELECT MAX(CustID)
FROM dbo.Customer;
END
ExecuteNonQuery() expects no results. Try ExecuteReader() instead.
I second what marc_S is saying about this running into issues.
Since you are using max ID and incrementing by 1 to insert a new record in the database, I suggest that you use Identity(seed, increment_value) for this column.
That way you don't have to find max to insert a new record and you avoid lots of transaction issues.
Once the transaction is done
Possible Design:
Create Table Customer
(
Id Int Identity(1,1),
Name varchar(50)
)
Create Proc NewCustomer
(
#Name varchar(50)
)
As
(
DECLARE #custID Int
SET NOCOUNT ON
INSERT INTO Customer (Name) Values('Your Name')
SET #custID = SCOPE_IDENTITY()
RETURN #custID
)
protected void btnNew_Click(object sender, EventArgs e)
{
Clear();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "NewCustomer";
conn.Open();
SqlParameter name = new SqlParameter();
name.ParameterName = "#Name";
name.Direction = ParameterDirection.Input;
name.SqlDbType = SqlDbType.Varchar;
name.Value = "Your Name";
command.Parameters.Add(name);
SqlParameter returnValue= new SqlParameter();
returnValue.ParameterName = "#custID";
returnValue.SqlDbType = SqlDbType.Int;
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(maxid);
command.ExecuteNonQuery();
NewCustId = Convert.ToInt32(returnValue.Value);
txtCustID.Text = (NewCustId).ToString();
txtCustID.DataBind();
conn.Close();
}

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

System.Data.SqlClient.SqlException: Implicit conversion from data type sql_variant to uniqueidentifier is not allowed.

I am facing this error when i try to edit my text in the ListView and subsequently update it in the database. This error message shows when i click on the update button in my ListView. As my UserID is a uniqueIdentifier, it cannot be updated to my database. But i do not really know what changes to make in my codes.
My error message shows this:
Implicit conversion from data type sql_variant to uniqueidentifier is not allowed. Use the CONVERT function to run this query.
My SQL Statement in .cs:
protected void updateComment(object sender, ListViewUpdateEventArgs e)
{
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
var ID= ListView1.DataKeys[e.ItemIndex].Value.ToString();
string connectionString = ConfigurationManager.ConnectionStrings["ASPNETConnectionString"].ConnectionString;
SqlConnection myConnect = new SqlConnection(connectionString);
string updateSql = "UPDATE Review set ContentRev =#ContentRev WHERE ID = #ID";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = new SqlCommand(updateSql, myConnection);
myCommand.Parameters.AddWithValue("#ID", ID);
myCommand.Parameters.AddWithValue("#ContentRev ", TextBox1.Text.Trim());
myCommand.ExecuteNonQuery();
myConnection.Close();
ListView1.DataBind();
}
My datatype for Userid is Object and ContentRev is String.
This is your problem:
var ID = ListView1.DataKeys[e.ItemIndex].Value.ToString();
If this is a uniqueIdentifier (or GUID), it should read:
Guid ID = new Guid(ListView1.DataKeys[e.ItemIndex].Value.ToString());
I actually think var ID will work, as long as the right side is a GUID.

Calling Stored procedure with output

I have been trying to retrieve some information from my database, and also retrieve the return value. I know the Stored Procedure works fine.
The code I use is a modified piece I use for registering the user. It's going wrong at the cmd.ExecuteReader part of my code.
protected void btn_login_Click(object sender, ImageClickEventArgs e)
{
//Actions after Submit button is clicked
Page.Validate(((ImageButton)sender).ValidationGroup);
if (Page.IsValid)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DbConnectString"].ConnectionString))
{
SqlCommand cmd = new SqlCommand("usp_validateUsers", conn);
//Input Values
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("username", Uname.Text);
cmd.Parameters.AddWithValue("password", pwd.Text);
//Return Values
SqlParameter retParam = cmd.Parameters.Add("#RetVal", SqlDbType.Int);
retParam.Direction = ParameterDirection.ReturnValue;
SqlParameter acsParam = cmd.Parameters.Add("#ac_status", SqlDbType.Int);
acsParam.Direction = ParameterDirection.Output;
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar);
nikParam.Direction = ParameterDirection.Output;
try
{
// Open Connection and execute Stored Proc
conn.Open();
///////////SOMETHING GOES WRONG HERE///////////////
cmd.ExecuteReader();
//Retrieve Data
int retVal = (int)retParam.Value;
string nickname = nikParam.Value.ToString();
string ac_stats = acsParam.Value.ToString();
if (retVal != 0)
{
//Invalid Username or password
}
else
{
//Login User
}
}
catch (Exception Error)
{
lbl_login.Text = "An error occured, please try again later";
debug.Text = Error.Message;
}
finally
{
debug.Text = "\n Clossing Connection";
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close();
}
}
}
}
}
When I just want to receive the return value I simply use cmd.ExecuteScalar(); I know how to receive data when I'm passing the SQL query to the SQL database, but it seems to be different when using Stored Procedures..
EDIT
Probably could improve this code further but it really does what it should do.
ALTER PROCEDURE dbo.usp_validateUsers
#username varchar(10),
#password varchar(10),
#ac_status char(1) OUTPUT,
#memb_name varchar(15) OUTPUT
AS
IF EXISTS(SELECT * FROM MEMB_INFO WHERE (memb___id = #username))
BEGIN
SELECT #ac_status = ac_status, #memb_name = memb_name
FROM MEMB_INFO
WHERE (memb___id = #username) AND (memb__pwd = #password)
RETURN 0
END
ELSE
BEGIN
return 1
END
When I use break points to catch possible exceptions in Visual Studio, It gives me:
String[4]: The Size property has an invalid size of 0
The error you mentioned may be caused by the fact that you're not specifying the size of your VarChar parameters. Instead of having lines like this:
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar);
Try this:
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar, 15);
You need to create a SqlDataReader.
From Ins and Outs of using Stored Procedures in C#
The SqlDataReader class is used to
read a forward only stream of records
returned from the database. The
SqlDataReader object is not
instantiated directly through a
constructor (hence the lack of the New
key word) but rather through the
ExecuteReader method of the SqlCommand
object. Before calling the
ExecuteReader method the connection to
the database is established using the
Open method of the SqlConnection
object.
Try
SqlDataReader drLogins;
Conn.Open();
drLogins = cmd.ExecuteReader();
Your #ac_status is defined as integer in parameter. change it character or string.
SqlParameter acsParam = cmd.Parameters.Add("#ac_status", SqlDbType.Int);

Categories