Insert/Update in asp.net and SQL SERVER 2008 - c#

I am trying to insert a record if requested prodName doesnot exist in database. If it exists I want to update the value of quantity attribute. I have used the following it neither inserts nor Updates any record. I get following exception:
ExecuteScalar requires an open and available Connection. The connection's current state is closed
This is the code
public static void manageStock(CompanyStock stock)
{
///// Check if record exists/////////
cmd = new SqlCommand("select count(*) from tblStock where prodName=#prodName", con);
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
con.Open();
Int32 count = (Int32)cmd.ExecuteScalar(); //returns null if doesnt exist
con.Close();
if (count > 0)
{
cmd = new SqlCommand("update tblStock set quantity = #quantity where prodName=#prodName", con);
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
cmd.Parameters.AddWithValue("#quantity", stock.quantity);
}
else
{
cmd = new SqlCommand("insert into tblStock(prodName,quantity) values (#prodName, #quantity)", con);
cmd.Parameters.AddWithValue("#prodName",stock.prodName);
cmd.Parameters.AddWithValue("#quantity",stock.quantity);
}
try
{
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
Edited
I edited my code. It works fine now. I had to open my connection before executing ExecuteScalar But I want to know the standard way of writing this opening and closing stuff. It looks kind of haphazard. How can I improve this?

You can use Convert.ToInt32() method for converting the result into integer value.
if the value is null it converts it into 0.
Try This:
int count = Convert.ToInt32(cmd.ExecuteScalar());

Consider using MERGE clause in sql-server. Here is a good Microsoft article you can use.

What does it do when you step through the code?
In some SQL collations (Latin1_General_BIN for example), variables are case sensitive. In your first select statement you have #ProdName in your query and #prodName in your parameters collection. If you have a case sensitive collation, you're never getting past this part. Right-click on the database in Management Studio and click Properties to find the collation.

Error say that there's no connection.May u check first of all that issue so
Check connection and if is not null and exist at this point check it con.State = Open or any other value. I connection state is closed open it.But first of all where is connections declaration ? i don't see it in your code.
TRY THIS :
//USING THE STATEMNET USING IT WILL TAKE CARE TO DISPOSE CONNECTION AND PLACE TRY CATCH WITHIN PROCS
{
using (SqlConnection cnn = new SqlConnection(ConfigurationManager.AppSettings("connectionString"))) {
if (cnn.State == System.Data.ConnectionState.Closed)
cnn.Open();
using (SqlCommand cmd = new SqlCommand()) {
try {
cmd.Connection = cnn;
cmd.CommandText = "YOUR SQL STATEMENT";
int I = Convert.ToInt32(cmd.ExecuteNonQuery);
if (I > 0)
{
cmd.CommandText = "YOUR SQL STATEMENT";
//ADDITIONAL PARAMTERES
}
else
{
cmd.CommandText = "YOUR SQL STATEMENT";
//ADDITIONAL PARAMETERS
}
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
}
}

You can try this code. First write a stored procedure:
CREATE PROCEDURE sprocquanupdateinsert
#prodName nvarchar(250),
#quantity int
AS
BEGIN
UPDATE tblStock
SET quantity = #quantity
WHERE prodName = #prodName
IF ##ROWCOUNT = 0
INSERT INTO tblStock(prodName, quantity)
VALUES (#prodName, #quantity)
END
GO
Then in code behind you can use this
using (conn)
{
SqlCommand cmd = new SqlCommand("sprocquanupdateinsert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
cmd.Parameters.AddWithValue("#quantity", stock.quantity);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}

Related

C# SQL Add parameter

I tried to return a row by executing following SQL query in C#:
SqlCommand cmd = new SqlCommand();
string selectquery = "SELECT TOP (1) [ZVNr] ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
cmd.CommandText = selectquery;
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
try
{
sqlConnection.Open();
int recordsAffected = cmd.ExecuteNonQuery();
if(recordsAffected != -1)
{
return 0;
}
else
{
return 1;
}
And the "ZVNR_TABLE" looks like this:
ZVNR | varchar (50)
20170530-01
The result is always --> recordsAffected = -1
Although when I'm executing the same SQL query in Microsoft SQL Server Management Studio, it works.
You're using a SELECT statement in your code with cmd.ExecuteNonQuery which is used for INSERT or UPDATE statements.
You have to use a SQLDataReader (more than 1 row and(!) column) or Scalar (1 row/1col = one "item").
MSDN Example for SQLDataReader:
//SELECT col1, col2, ..., coln FROM tbl;
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
reader.GetString(1));
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
MSDN Example for ExecuteScalar:
//SELECT COUNT(*) FROM region; or any other single value SELECT statement
int count = (int)cmd.ExecuteScalar(); //cast the type as needed
If you want the affected count after you change items in your database, you can get it by using cmd.ExecuteNonQuery which returns that count:
MSDN Example for ExecuteNonQuery:
//INSERT INTO tbl (...) VALUES (...) or any other non-query statement
int rowsAffected = (Int32)cmd.ExecuteNonQuery();
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command.
Because you are Selecting the data from the datatable not inserting or updating the records that's why recordsAffected is always -1
Answers given above are ok but if you want just to see if it exist you can do a count instead
using (SqlConnection connection = new SqlConnection(connectionstring))
{
string query = "SELECT Count([ZVNr]) ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
try
{
connection.Open();
int result = (int)cmd.ExecuteScalar();
}
}
}
ExecuteNonQuery() is used for INSERT or UPDATE statements and returns the number of rows affected.
If you want to return a single field of a row, you have to use ExecuteScalar()
using (SqlConnection connection = new SqlConnection(connectionstring))
{
string query = "SELECT TOP (1) [ZVNr] ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
connection.Open();
object result = cmd.ExecuteScalar();
}
}

Check if a specific row exists, and if it doesn't, add a new one

I'm beginner in SQL and C#. My question is: how do I check whether a row in the table exists or not? Here is my code that I am currently using:
var conn = new SqlConnection(#"Data Source");
conn.Open();
var cmd = new SqlCommand("INSERT INTO Results (PlayerName) VALUES (#PlayerName) " , conn);
cmd.Parameters.Add("#PlayerName",_playerName);
cmd.ExecuteNonQuery();
conn.Close();
I want to check if the player name exists or not, and if not, then add it to the table.
You can check it with Select statement first and then insert it if it is not exist.
Also use using statement to dispose your connection and commands automatically instead of calling Close method manually.
using(var conn = new SqlConnection(yourConnectionString))
using(var cmd = conn.CreateCommand())
{
cmd.CommandText = "Select Count(*) From Results Where PlayerName = #playerName";
cmd.Parameters.Add("#playerName", _playerName);
con.Open();
int count = (int)cmd.ExecuteScalar();
if(count == 0)
{
// It means it does not exist.
cmd.CommandText = "INSERT INTO Results(PlayerName) VALUES (#playerName)";
cmd.ExecuteNonQuery();
}
}
if not exists(select null from Results where PlayerName=#PlayerName) begin INSERT INTO Results (PlayerName) VALUES (#PlayerName) end

Insert statement into SQL Server database

I'm trying to find this bug for the last several days, but without any success.
I'm trying to insert one new row in a database. Everything goes well: there is no error, and no program crashes.
My INSERT statement looks like this:
INSERT INTO Polozaj(Znesek, Uporabnik, Cas, Kupec, Popust, Poln_znesek)
VALUES(1,1,1,1,1,1)
That statement is ok, because when I run the query in my database it adds the new row.
My C# code looks like this:
string connection = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=" + Application.StartupPath + "\\Trgovina.mdf;Integrated Security=True";
SqlConnection cn = new SqlConnection(connection);
string payment = ((Button)sender).Text, maxID = string.Empty;
double discount = Convert.ToDouble(discauntText.Text), totalPrice = Convert.ToDouble(fullPriceText.Text), fullPrice = Convert.ToDouble(discountPriceText.Text);
switch (payment)
{
case "Dobavnica": discount = 10; break;
case "Kartica": discount = 0; break;
case "Gotovina": discount = 5; break;
}
cn.Open();
SqlCommand maxIdCmd = new SqlCommand("SELECT MAX(Id_racuna) FROM Racun", cn);
maxID = Convert.ToString(maxIdCmd.ExecuteScalar());
maxID = maxID != "" ? Convert.ToString(Convert.ToInt32(maxID) + 1) : "1";
string stmt = "INSERT INTO Racun(Znesek, Uporabnik, Cas, Kupec, Popust, Poln_znesek) " +
"VALUES(#Price, #User, #Time, #Customer, #Discount, #FullPrice)";
SqlCommand cmd = new SqlCommand(stmt, cn);
cmd.ExecuteNonQuery();
cn.Close();
As I already mentioned, it looks like the program runs this query and everything is just normal, but when I look in the table Racun, there is no new row. Furthermore, when I try to refresh this table data visual studio (2012) gives me an error that looks like: This database cannot be imported. It is either unsupported SQL Server version or an unsupported database compatibility.
And my table Racun create query looks like this:
CREATE TABLE [dbo].[Racun] (
[Id_racuna] INT IDENTITY (1, 1) NOT NULL,
[Znesek] NUMERIC (10, 3) NULL,
[Uporabnik] NCHAR (20) NULL,
[Cas] NCHAR (15) NULL,
[Kupec] NCHAR (10) NULL,
[Popust] NUMERIC (10, 3) NULL,
[Poln_znesek] NUMERIC (10, 3) NULL,
PRIMARY KEY CLUSTERED ([Id_racuna] ASC)
);
I don't know what's going wrong. Can anyone help?
There is three possible scenarios for an insert like that:
The insert succeeds.
You get an exception.
You have a trigger that replaces the insert with some other action.
I guess that you don't have a trigger, and as you don't get a record in the table, there has to be an exception.
Do you have any code that catches the exception at any other level? That would explain why you don't see it, and it would also leave the database connection unclosed, which would explain why you have problems connecting to the database afterwards.
Using a using block for the database connection would close it properly even if there is an error in the code.
You are using a parameterised query, but I can't see that you add the parameters to the command object anywhere in the code. That would be something like:
cmd.Parameters.Add("Price", SqlDbType.Decimal).Value = price;
cmd.Parameters.Add("User", SqlDbType.NChar, 20).Value = user;
cmd.Parameters.Add("Time", SqlDbType.NChar, 15).Value = time;
cmd.Parameters.Add("Customer", SqlDbType.NChar, 10).Value = customer;
cmd.Parameters.Add("Discount", SqlDbType.Decimal).Value = discount;
cmd.Parameters.Add("FullPrice", SqlDbType.Decimal).Value = fullPrice;
I would try wrapping your code in a try block, and see if you can catch a SqlExecption:
try {
SqlCommand cmd = new SqlCommand(stmt, cn);
cmd.ExecuteNonQuery();
} catch (SqlException ex) {
Console.WriteLine(ex.Message);
}
Edit: It looks like you're missing your parameters for your INSERT statement, and you should probably look at using a SqlTransaction:
SqlCommand maxIdCmd = new SqlCommand("SELECT MAX(Id_racuna) FROM Racun", cn);
maxID = Convert.ToString(maxIdCmd.ExecuteScalar());
maxID = maxID != "" ? Convert.ToString(Convert.ToInt32(maxID) + 1) : "1";
string stmt = "INSERT INTO Racun(Znesek, Uporabnik, Cas, Kupec, Popust, Poln_znesek) " +
"VALUES(#Price, #User, #Time, #Customer, #Discount, #FullPrice)";
SqlCommand cmd = new SqlCommand(stmt, cn);
// Adding parameters to the insert statement:
cmd.Parameters.AddWithValue("#Price", price);
cmd.Parameters.AddWithValue("#User", user);
cmd.Parameters.AddWithValue("#Time", time);
cmd.Parameters.AddWithValue("#Customer", customer);
cmd.Parameters.AddWithValue("#Discount", discount);
cmd.Parameters.AddWithValue("#FullPrice", fullprice);
// Start a transaction so we can roll back if there's an error:
SqlTransaction transaction = cn.BeginTransaction();
cmd.Transaction = transaction;
try {
cmd.ExecuteNonQuery();
transaction.Commit();
} catch (SqlException ex) {
transaction.Rollback();
Console.WriteLine(ex.Message);
} finally {
cn.Close();
}

Accessing SQL Server stored procedure output parameter in C#

I have a simple SQL Server stored procedure:
ALTER PROCEDURE GetRowCount
(
#count int=0 OUTPUT
)
AS
Select * from Emp where age>30;
SET #count=##ROWCOUNT;
RETURN
I am trying to access the output parameter in the following C# code:
SqlConnection con = new SqlConnection();
con.ConnectionString = "Data Source=localhost\\SQLEXPRESS;Initial Catalog=answers;Integrated Security=True";
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "GetRowCount";
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#count", SqlDbType.Int));
cmd.Parameters["#count"].Direction = ParameterDirection.Output;
con.Open();
SqlDataReader reader=cmd.ExecuteReader();
int ans = (int)cmd.Parameters["#count"].Value;
Console.WriteLine(ans);
But on running the code, a NullReferenceException is being thrown at the second last line of the code. Where am I going wrong? Thanks in advance!
P.S. I am new to SQL Procedures, so I referred this article.
I'd suggest you put your SqlConnection and SqlCommand into using blocks so that their proper disposal is guaranteed.
Also, if I'm not mistaken, the output parameters are only available after you've completely read the resulting data set that's being returned.
Since you don't seem to need that at all - why not just use .ExecuteNonQuery() instead? Does that fix the problem?
using (SqlConnection con = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=answers;Integrated Security=True"))
using (SqlCommand cmd = new SqlCommand("dbo.GetRowCount", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#count", SqlDbType.Int));
cmd.Parameters["#count"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery(); // *** since you don't need the returned data - just call ExecuteNonQuery
int ans = (int)cmd.Parameters["#count"].Value;
con.Close();
Console.WriteLine(ans);
}
Also : since it seems you're only really interested in the row count - why not simplify your stored procedure to something like this:
ALTER PROCEDURE GetRowCount
AS
SELECT COUNT(*) FROM Emp WHERE age > 30;
and then use this snippet in your C# code:
con.Open();
object result = cmd.ExecuteScalar();
if(result != null)
{
int ans = Convert.ToInt32(result);
}
con.Close();
you have to specify that it is a stored procedure not a query
cmd.CommandType = CommandType.StoredProcedure;
Just use ExecuteNonQuery , you can't use ExecuteReader with out parameter in this case
cmd.ExecuteNonQuery();
Or if you want try with ExecuteScalar and ReturnValue
You should add
cmd.CommandType = CommandType.StoredProcedure
before calling it
I find the problem, its the connection string.
But now, in the code:
usuary = (string)cmd.Parameters["#USUARIO"].Value;
password = (string)cmd.Parameters["#CLAVE"].Value;
the compiler infomrs thats values are null...

Insert data into SQL Server from C# code

I have a table student (id, name). Then I have one textbox, for entering the name, when click on submit button, it inserts the data into the database. So how can I insert only to name, not id because id is auto increment?
I tried this
insert into student(id, name) values(,name)
but it is not insert to my table.
This is my code :
protected void Button1_Click(object sender, EventArgs e)
{
string test = txtName.Text;
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Person.mdf;Integrated Security=True;User Instance=True");
string sql = "insert into student(name) values ('test')";
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
}
finally
{
conn.Close();
}
}
INSERT INTO student (name) values ('name')
Omit the id column altogether, it will be populated automatically. To use your variable, you should parameterise your SQL query.
string sql = "INSERT INTO student (name) values (#name)";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.Add("#name", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = test;
cmd.ExecuteNonQuery();
You should never attempt to do this by constructing a SQL string containing the input value, as this can expose your code to SQL injection vulnerabilities.
You better use parameters when you insert data.
try
{
string sql = "insert into student(name) values (#name)";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("#name", test); // assign value to parameter
cmd.ExecuteNonQuery();
}
}
}
catch (SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
}
You don't need to mention the ID in first part.
insert into student(name) values('name')
I was facing this problem and after trying various solution found at stack overflow, i could summarize the experience as follows:
commands executed in command shell of mssql like:
insert into table_name (val1,val2,val3,val4) VALUES ("val1","val2",0,"val4")
go
or
insert into table_name VALUES ("val1","val2",0,"val4")
go
work when typed directly in the mssql database prompt,
But when it is required to use the the insert statement from c#, it is required to be kept in mind that string needs to be surrounded by an additional pair of single quites, around the strings, like in:
SqlConnection cnn;
string connetionString = "Data Source=server_name;Initial Catalog=database_name;User ID=User_ID;Password=Pass_word";
cnn = new SqlConnection(connetionString);
SqlCommand myCommand = new SqlCommand("insert into table_name (val1,val2,val3,val4) VALUES ('val1','val2',0,'val4');", cnn);
//or
//SqlCommand myCommand = new SqlCommand(insert into table_name VALUES ('val1','val2',0,'val4');", cnn);
cnn.Open();
myCommand.ExecuteNonQuery();
cnn.Close();
the problem here is that most people, like myself, try to use <\"> in the place of double quotes <">that is implemented as in the above command line case, and SQL executor fails to understand the meaning of this.
Even in cases where a string needs to be replace, ensure that strings are surrounded by single quotation, where a string concatination looks like a feasible solution, like in:
SqlCommand myCommand = new SqlCommand("insert into table_name (val1,val2,val3,val4) VALUES ('"+val1+"','val2',0,'val4');", cnn);
string sql = "INSERT INTO student (name) values (#name)";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.Add("#name", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = test;
cmd.ExecuteNonQuery();
Try the following query,
insert into student(name) values(name)
SQL Server internally auto increments the id column when u insert the data since u said it is auto increment. If it is not working, the u have to check the identity column in the db.
use the key word "identity" to auto increment the id column
Refer : http://technet.microsoft.com/en-us/library/aa933196(v=sql.80).aspx
create table table_name( id int PRIMARY KEY IDENTITY )
and you no need to mention the "id" in the insert query

Categories