Proper use of AddWithValue in C# to Db method - c#

Trying to do the following:
public static int GetJobStatusByNumber(int jobNumber)
{
SqlConnection connection = null;
try
{
connection = new SqlConnection(connString);
connection.Open();
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = #"select STATUS from JOB
where JOB_NUMBER = #jobNumber";
cmd.Parameters.AddWithValue("#jobNumber", jobNumber);
int result = ((int)cmd.ExecuteScalar());
return result;
}
finally
{
if (connection != null)
connection.Close();
}
}
Thouht I can add the varible 'jobNumber' to the query by using 'AddWithValue' but I'm getting a cast error
Message: System.InvalidCastException : Specified cast is not valid.
What's wrong here?
Thanks.

ExecuteScalar() returns the first column of the first row in the result set returned by the query.
2 scenarios are possible:
the first column is not a int.
the query return 0 rows - in that case ExecuteScalar() will return null.
for point 1 - make sure that the first column is an int.
for point 2 - make sure you have rows. possible solution will be:
var result = 0;
var tempResult = cmd.ExecuteScalar();
if (tempResult != null) {
result = (int)tempResult;
}

Related

"Select count()" returns wrong value

I am trying to determine if a specific value exists in a Oracle database table.
I used a query with "select count(*)", "select count(1)" and select count(<col_name>)" but keep getting the wrong result. When I use SQL Developer and run the query I get zero for the count. However, in the DAL, I get 1. I am guessing it is returning the number of row rather than the count itself. I tried both executeScalar() and ExecuteReader().
public override bool zipExists(string sZipCode)
{
OracleConnection conn = new OracleConnection(this.OraDataConnectionString);
OracleCommand oraCmd = new OracleCommand();
decimal iNumEntries = 0;
string sQuery = "select count(ZIPCODEID) as ZipCount from ZIPCODE where ZIPCODE = :ZipCode";
SetOraCommandType(oraCmd, CommandType.Text, sQuery);
conn.Open();
oraCmd.Connection = conn;
oraCmd.BindByName = true;
AddParamToOraCmd(oraCmd, "ZipCode", OracleDbType.Varchar2, 11, ParameterDirection.Input, sZipCode);
using (OracleConnection cn = new OracleConnection(this.OraDataConnectionString))
{
oraCmd.Connection = cn;
cn.Open();
iNumEntries = (decimal)oraCmd.ExecuteScalar();
}
return iNumEntries > 0;
also tried:
OracleDataReader sqlReader = oraCmd.ExecuteReader();
try
{
if (sqlReader.Read())
{
if (sqlReader["ZipCount"] != DBNull.Value)
iNumEntries = Convert.ToInt16(sqlReader["ZipCount"]);
}
}
}
return iNumEntries > 0;
I try you code on my table but pointing to some column and giving a select count(EN_Qty) as ZipCount from PSLAT.FSDEV.dbo.PS_EN_GEN_INTFC_BI where EN_Qty = '2600' works on my end so where in the code exactly are you experiencing an issue..? fyi I replaced my table with your query and assigned a value to the where clause.. so you query looks right.. however I would do an order by query to see if you perhaps are missing a zipcode..also oraCmd.ExecuteScalar() returns only 1 row so make sure you are not returning more than one row..oracle is funny like that
change your code to the following
object bExists = oraCmd.ExecuteScalar();
var bexists = bExists != DBNull.Value && result != null;
or change your code to check for row.count > 0 if true then you know the zipcode was found. Remember when making changes to Sql scripts or stored procedures in Oracle, you need to Compile the changes otherwise the changes will be visible to you when looking at the code but not to the caller trying to execute the stored proc.

Why is ExecuteScalar returning NullReferenceException error [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
ExecuteScalar returns null or DBNull (development or production server)
(3 answers)
Closed 8 years ago.
I have the following function which checks to see if a user(strU) exist in the table for a column, if so return 1, otherwise return 0:
public int AddDataScalar(string strU)
{
string strQueryExistence = "SELECT 1 FROM [OB].[h].[OP_PEONS] WHERE Executive= '" + strU + "'";
int inNum;
using (SqlConnection con = new SqlConnection(strConn))
{
con.Open();
SqlCommand cmd = new SqlCommand(strQueryExistence, con);
object value = cmd.ExecuteScalar().ToString();
if (value != null)
{
inNum = 1;
}
else
{
inNum = 0;
}
con.Close();
}
return inNum;
}
It is failing in this line: object value = cmd.ExecuteScalar().ToString();
With the following error: Object reference not set to an instance of an object.
How do I resolve it?
ExecuteScalar returns null if your WHERE condition doesn't produce any result.
If you apply any kind of conversion when ExecuteScalar returns null you are in trouble.
Said that, I really suggest some changes to your query
public int AddDataScalar(string strU)
{
string strQueryExistence = #"IF EXISTS(SELECT 1 FROM [OB].[h].[OP_PEONS]
WHERE Executive= #stru) SELECT 1 ELSE SELECT 0";
int inNum = 0;
using (SqlConnection con = new SqlConnection(strConn))
using ( SqlCommand cmd = new SqlCommand(strQueryExistence, con))
{
con.Open();
cmd.Parameters.AddWithValue("#stru", strU);
inNum = Convert.ToInt32(cmd.ExecuteScalar());
}
return inNum;
}
The first thing is the IF EXISTS t-sql functions that is the fastest way to discover if a specific record exists or not in the table. The second point is the usage of a parameterized query to avoid parsing problems and Sql Injection scenarios.
The IF EXISTS statement allows to be sure that the ExecuteScalar doesn't return null because in that case the ELSE part will return zero
whenever cmd.ExecuteScalar() returns null then null.ToString() throws the exception.
In your case, just use teкnary operator:
inNum = cmd.ExecuteScalar() == null ? 0 : 1;
The implementation could be
public int AddDataScalar(string strU) {
using (SqlConnection con = new SqlConnection(strConn)) {
con.Open();
// Make your SQL readable: use #"" strings
strQueryExistence =
#"SELECT 1
FROM [OB].[h].[OP_PEONS]
WHERE Executive = #prm_Executive";
// using is a better practice
using (SqlCommand cmd = new SqlCommand(strQueryExistence, con)) {
// parameters are better than hardcoding
cmd.Parameters.AddWithValue("#prm_Executive", strU);
return cmd.ExecuteScalar() == null ? 0 : 1;
}
}
}
According to MSDN (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx):
The first column of the first row in the result set, or a null reference (Nothing in Visual Basic) if the result set is empty.
You're calling .ToString() (why?) on a null object, since there are no results being returned. Skip the .ToString() call and it should work fine.
If object returned by cmd.ExecuteScalar() is null, you will get this exception. Use:
string value = System.Convert.ToString(cmd.ExecuteScalar());
if you need the result converted to string.

OledbDataReader function to return integer

Working in C#, I'm having trouble with a function. Function runs a query and the query is supposed to return one integer value but I'm having trouble returning it. I keep getting errors like:
Unable to cast object of type oleDbDataReader to type Int32
Specified cast is not valid
Not sure how to do this with C# and OleDbDataReader. My code is below
public static int FifthQuery()
{
int _value = 0;
OleDbConnection _connectMe = Utilities.OledbConnect();
OleDbCommand _query1 = new OleDbCommand();
_query1.Connection = _connectMe;
_query1.CommandText = "SELECT count(*) FROM GIS.PERSONS where Name_Prefix = 'Dr.'";
OleDbDataReader _reader = _query1.ExecuteReader();
_reader.Read();
//_value = Convert.ToInt32(_reader);
_value = _reader.GetInt32(0);
return _value;
}
Since you using COUNT(*), using ExecuteScalar would be better approach.
Executes the query, and returns the first column of the first row in
the result set returned by the query.
int _value = (int)_query1.ExecuteScalar();
Also use using statement to dispose your OleDbConnection and OleDbCommand.
using(OleDbConnection _connectMe = Utilities.OledbConnect())
using(OleDbCommand _query1 = _connectMe.CreateCommand())
{
_query1.CommandText = "SELECT count(*) FROM GIS.PERSONS where Name_Prefix = 'Dr.'";
_connectMe.Open();
int _value = (int)_query1.ExecuteScalar();
}

Cast error in C#

I have a function in a class "Checkout" that runs a sql statement to insert a record into a table, then select the scope_identity, giving me the ID of that record. It returns the ID as an int, and I assign it to a variable in the webpage:
int OrderID = Checkout.WriteOrder_tblOrders(CustID);
Here's the function:
public static int WriteOrder_tblOrders(int CustID)
{
// OrderID is initially 0, then changed when scope_identity is called in the sql statement.
int OrderID = 0;
DateTime OrderDate = DateTime.Now;
string sql = "INSERT INTO tblOrders (OrderDate, CustID) VALUES (#OrderDate, #CustID); SELECT scope_identity();";
using (SqlConnection myConnection = new SqlConnection(connectString))
{
using (SqlCommand cmd = new SqlCommand(sql, myConnection))
{
cmd.Parameters.AddWithValue("#CustID", CustID);
cmd.Parameters.AddWithValue("#OrderDate", OrderDate);
myConnection.Open();
OrderID = (int)cmd.ExecuteScalar();
myConnection.Close();
}
}
return OrderID;
}
The debugger shows that there's nothing wrong with the function, and new records are showing up correctly in that table, but I'm getting an
"Invalid Cast"
error on the first line, where I assign OrderID. I've tried this:
int OrderID = (int)Checkout.WriteOrder_tblOrders(CustID);
With both int and Int32, and also tried using Convert.ToInt32, which didn't work either. What am I doing wrong here?
The reason may be you are getting null values.
So you ca create an extension method as follows
public static T ExecuteNullableScalar<T>(this SqlCommand cmd) where T : struct
{
var result = cmd.ExecuteScalar();
if (result == DBNull.Value) return default(T);
return (T)result;
}
Usage becomes:
int value = cmd.ExecuteNullableScalar<int>();
//new approach
ulong value=cmd.ExecuteNullableScalar<ulong>();
Other-Wise
myConnection.Open();
var o = cmd.ExecuteScalar();
OrderID = (o== DBNull.Value ? 0 : Convert.ToUInt64(o));
myConnection.Close();
changed
OrderID = (o== DBNull.Value ? 0 : Convert.ToUInt64(o));
Thanks for your help guys, didn't realize that scope_identity returns a decimal. I altered the code like this:
OrderID = Convert.ToInt32((decimal)cmd.ExecuteScalar());
It now works fine. Thanks!

Handling ExecuteScalar() when no results are returned

I am using the following SQL query and the ExecuteScalar() method to fetch data from an Oracle database:
sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();
It is showing me this error message:
System.NullReferenceException: Object reference not set to an instance of an object
This error occurs when there is no row in the database table for userid=2.
How should I handle this situation?
According to MSDN documentation for DbCommand.ExecuteScalar:
If the first column of the first row in the result set is not found, a
null reference (Nothing in Visual Basic) is returned. If the value in
the database is null, the query returns DBNull.Value.
Consider the following snippet:
using (var conn = new OracleConnection(...)) {
conn.Open();
var command = conn.CreateCommand();
command.CommandText = "select username from usermst where userid=2";
string getusername = (string)command.ExecuteScalar();
}
At run-time (tested under ODP.NET but should be the same under any ADO.NET provider), it behaves like this:
If the row does not exist, the result of command.ExecuteScalar() is null, which is then casted to a null string and assigned to getusername.
If the row exists, but has NULL in username (is this even possible in your DB?), the result of command.ExecuteScalar() is DBNull.Value, resulting in an InvalidCastException.
In any case, the NullReferenceException should not be possible, so your problem probably lies elsewhere.
First you should ensure that your command object is not null. Then you should set the CommandText property of the command to your sql query. Finally you should store the return value in an object variable and check if it is null before using it:
command = new OracleCommand(connection)
command.CommandText = sql
object userNameObj = command.ExecuteScalar()
if (userNameObj != null)
string getUserName = userNameObj.ToString()
...
I'm not sure about the VB syntax but you get the idea.
I just used this:
int? ReadTerminalID()
{
int? terminalID = null;
using (FbConnection conn = connManager.CreateFbConnection())
{
conn.Open();
FbCommand fbCommand = conn.CreateCommand();
fbCommand.CommandText = "SPSYNCGETIDTERMINAL";
fbCommand.CommandType = CommandType.StoredProcedure;
object result = fbCommand.ExecuteScalar(); // ExecuteScalar fails on null
if (result.GetType() != typeof(DBNull))
{
terminalID = (int?)result;
}
}
return terminalID;
}
The following line:
string getusername = command.ExecuteScalar();
... will try to implicitly convert the result to string, like below:
string getusername = (string)command.ExecuteScalar();
The regular casting operator will fail if the object is null.
Try using the as-operator, like this:
string getusername = command.ExecuteScalar() as string;
sql = "select username from usermst where userid=2"
var _getusername = command.ExecuteScalar();
if(_getusername != DBNull.Value)
{
getusername = _getusername.ToString();
}
Check out the example below:
using System;
using System.Data;
using System.Data.SqlClient;
class ExecuteScalar
{
public static void Main()
{
SqlConnection mySqlConnection =new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;");
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText ="SELECT COUNT(*) FROM Employee";
mySqlConnection.Open();
int returnValue = (int) mySqlCommand.ExecuteScalar();
Console.WriteLine("mySqlCommand.ExecuteScalar() = " + returnValue);
mySqlConnection.Close();
}
}
from this here
SQL NULL value
equivalent in C# is DBNull.Value
if a NULLABLE column has no value, this is what is returned
comparison in SQL: IF ( value IS NULL )
comparison in C#: if (obj == DBNull.Value)
visually represented in C# Quick-Watch as {}
Best practice when reading from a data reader:
var reader = cmd.ExecuteReader();
...
var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString());
In my experience, there are some cases the returned value can be missing and thus execution fails by returning null. An example would be
select MAX(ID) from <table name> where <impossible condition>
The above script cannot find anything to find a MAX in. So it fails. In these such cases we must compare the old fashion way (compare with C# null)
var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));
If you either want the string or an empty string in case something is null, without anything can break:
using (var cmd = new OdbcCommand(cmdText, connection))
{
var result = string.Empty;
var scalar = cmd.ExecuteScalar();
if (scalar != DBNull.Value) // Case where the DB value is null
{
result = Convert.ToString(scalar); // Case where the query doesn't return any rows.
// Note: Convert.ToString() returns an empty string if the object is null.
// It doesn't break, like scalar.ToString() would have.
}
return result;
}
Always have a check before reading row.
if (SqlCommand.ExecuteScalar() == null)
{
}
This is the easiest way to do this...
sql = "select username from usermst where userid=2"
object getusername = command.ExecuteScalar();
if (getusername!=null)
{
//do whatever with the value here
//use getusername.toString() to get the value from the query
}
In your case either the record doesn't exist with the userid=2 or it may contain a null value in first column, because if no value is found for the query result used in SQL command, ExecuteScalar() returns null.
Alternatively, you can use DataTable to check if there's any row:
SqlCommand cmd = new SqlCommand("select username from usermst where userid=2", conn);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
string getusername = "";
// assuming userid is unique
if (dt.Rows.Count > 0)
getusername = dt.Rows[0]["username"].ToString();
private static string GetUserNameById(string sId, string connStr)
{
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
System.Data.SqlClient.SqlCommand command;
try
{
// To be Assigned with Return value from DB
object getusername;
command = new System.Data.SqlClient.SqlCommand();
command.CommandText = "Select userName from [User] where userid = #userid";
command.Parameters.AddWithValue("#userid", sId);
command.CommandType = CommandType.Text;
conn.Open();
command.Connection = conn;
//Execute
getusername = command.ExecuteScalar();
//check for null due to non existent value in db and return default empty string
string UserName = getusername == null ? string.Empty : getusername.ToString();
return UserName;
}
catch (Exception ex)
{
throw new Exception("Could not get username", ex);
}
finally
{
conn.Close();
}
}
Slight conjecture: if you check the stack for the exception, it is being thrown then the ADO.NET provider for Oracle is reading the underlying rowset to get the first value.
If there is no row, then there is no value to find.
To handle this case execute for a reader and handle Next() returning false for the case of no match.
I Use it Like This with Microsoft Application Block DLL (Its a help library for DAL operations)
public string getCopay(string PatientID)
{
string sqlStr = "select ISNULL(Copay,'') Copay from Test where patient_id=" + PatientID ;
string strCopay = (string)SqlHelper.ExecuteScalar(CommonCS.ConnectionString, CommandType.Text, sqlStr);
if (String.IsNullOrEmpty(strCopay))
return "";
else
return strCopay ;
}
I have seen in VS2010
string getusername = command.ExecuteScalar();
gives compilation error,
Cannot implicitly convert type object to string.
So you need to write
string getusername = command.ExecuteScalar().ToString();
when there is no record found in database it gives error
Object reference not set to an instance of an object
and when I comment '.ToString()', it is not give any error. So I can say ExecuteScalar not throw an exception. I think anserwer given by #Rune Grimstad is right.
I had this issue when the user connecting to the database had CONNECT permissions, but no permissions to read from the database. In my case, I could not even do something like this:
object userNameObj = command.ExecuteScalar()
Putting this in a try/catch (which you should probably be doing anyway) was the only way I could see to handle the insufficient permission issue.
object objUserName;
objUserName = command.ExecuteScalar();
if (objUserName == null) //if record not found ExecuteScalar returns null
{
return "";
}
else
{
if (objUserName == DBNull.Value) //if record found but value in record field is null
{
return "";
}
else
{
string getusername = objUserName.ToString();
return getusername;
}
}
/* Select some int which does not exist */
int x = ((int)(SQL_Cmd.ExecuteScalar() ?? 0));
I used this in my vb code for the return value of a function:
If obj <> Nothing Then
Return obj.ToString()
Else
Return ""
End If
Try this code, it appears to solve your problem.
Dim MaxID As Integer = Convert.ToInt32(IIf(IsDBNull(cmd.ExecuteScalar()), 1, cmd.ExecuteScalar()))
I'm using Oracle.
If your sql returns numeric value, which is int, you need to use Convert.ToInt32(object). Here is the example below:
public int GetUsersCount(int userId)
{
using (var conn = new OracleConnection(...)){
conn.Open();
using(var command = conn.CreateCommand()){
command.CommandText = "select count(*) from users where userid = :userId";
command.AddParameter(":userId", userId);
var rowCount = command.ExecuteScalar();
return rowCount == null ? 0 : Convert.ToInt32(rowCount);
}
}
}
Try this
sql = "select username from usermst where userid=2"
string getusername = Convert.ToString(command.ExecuteScalar());

Categories

Resources