Specified Cast is not valid - C# - c#

I'm trying to do an AppendLine with this
reportLayout.AppendLine(
"Sold Items".PadRight(25) +
Convert.ToString(BatchCalculation.NoOfItems(dBCommand, transDate, reportType)));
And I'm getting an exception thrown
Specified Cast is not valid
my NoOfItems is a static method and it returns an int
EDIT: Last lines of code in NoOfItems method
...
using (DbDataReader reader = dBCommand.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
//hsBatch.currentTC = (int)reader["CURRENTTC"];
//hsBatch.currentAmt = (decimal)reader["CURRENTPYMTAMT"];
//Cancellation fee
hsBatch.TotalNoOfitems = (int)reader["TOTALNOOFITEMS"];
}
}
}
}
}
finally
{
if (connection.State == ConnectionState.Open)
connection.Close();
}
return hsBatch.TotalNoOfitems;
}

Database can return null, so I would suggest to check DBNull
hsBatch.TotalNoOfitems = reader["TOTALNOOFITEMS"] != DBNull.Value ? int.Parse(reader["TOTALNOOFITEMS"].ToString()):0;

It seems you have a problem with type mapping (RDBMS Number is not necessary .Net int):
// (int) - cast like this may well be incorrect:
// reader["TOTALNOOFITEMS"] is not nesseary int or can be cast to int
hsBatch.TotalNoOfitems = (int)reader["TOTALNOOFITEMS"];
Instead of
if (reader.HasRows)
{
while (reader.Read())
{
//hsBatch.currentTC = (int)reader["CURRENTTC"];
//hsBatch.currentAmt = (decimal)reader["CURRENTPYMTAMT"];
//Cancellation fee
hsBatch.TotalNoOfitems = (int)reader["TOTALNOOFITEMS"];
}
}
Put
// if: we don't want "while" since we read one record only
// reader.HasRows is redundant - if we manage to read a record we have it
if (reader.Read())
{
// hsBatch.currentTC = Convert.ToInt32(reader["CURRENTTC"]);
// hsBatch.currentAmt = Convert.ToDecimal(reader["CURRENTPYMTAMT"]);
// What ever RDBMS type mapping is (byte, short, int, long, decimal
// or even string - depending on query, RDBMS and settings)
// try convert it into int - Int32
hsBatch.TotalNoOfitems = Convert.ToInt32(reader["TOTALNOOFITEMS"]);
}
There's one more (possible) issue: if TOTALNOOFITEMS field contains NULL value. If it's your case, you can put
hsBatch.TotalNoOfitems = reader["TOTALNOOFITEMS"] == DBNull.Value
? 0 // or whatever value in case of null
: Convert.ToInt32(reader["TOTALNOOFITEMS"]);

Related

How can I change a bool to a 0 or a 1, can I cast it?

I have this method:
public void UpdatePhrase(PHRASE phraseColumn, bool value, string phraseId)
{
sql = string.Format("UPDATE Phrase SET " + phraseColumn.Text() + " = {0} WHERE PhraseId = '{1}'", value, phraseId);
App.DB.RunExecute(sql);
}
It's not working correctly as it seems like I need the value of {0} needs to be a 0 or a 1.
Is there a simple way that I can take value and change it to be a 0 or a 1?
Just do value ? 1 : 0, it's that easy!
#Sean has given to you the natural fix to your problem, but, in my view, what you really need to do here is to refactor your App.Db.RunExecute to receive parameters, so you can write
public void UpdatePhrase(PHRASE phraseColumn, bool value, string phraseId)
{
sql = "UPDATE Phrase SET " + phraseColumn.Text() + " = #v WHERE PhraseId = #id";
List<SqlParameter> prms = new List<SqlParameter>
{
new SqlParameter {ParameterName = "#v", SqlDbType = SqlDbType.Boolean, Value = value},
new SqlParameter {ParameterName = "#id", SqlDbType = SqlDbType.NVarChar, Value = phraseId}
};
App.DB.RunExecute(sql, prms);
}
This will partially remove the Sql Injection problem (I say partially because that phraseColumn.Text() is still source of concerns if its value comes from the user input)
Now RunExecute should change to
void RunExecute(string sqlCommand, List<SqlParameter> prms = null)
{
// usual code to open connection and create a command
......
// If the caller passes a parameters list, add them to the command
if(prms != null)
cmd.Parameters.AddRange(prms.ToArray());
// Now execute the command
cmd.ExecuteNonQuery();
}
The change to RunExecute uses an optional argument, so your current code is not affected by the presence of the new argument but you will be able to write better Sql code from now on.
value ? 1 : 0
as in #Sean answer or
Convert.ToInt32(value)
ToInt32(Boolean) Converts the specified Boolean value to the
equivalent 32-bit signed integer.
You can use the int count = updateCommand.ExecuteNonQuery; so if count>0, it means our mission is done 1 (True) , otherwise 0 (False)
updateCommand.Parameters.AddWithValue("#Var" , "Johne");
try
{
connection.Open();
int count = updateCommand.ExecuteNonQuery;
if (count > 0)
return true;
else
return false;
}
catch (SqlException ex)
{
throw ex;
}
finally
{
connection.Close();
}
}
I hope you got the point ^_^.
you can do (GetHashCode on booleans returns a constant 1/0, no calculation):
true.GetHashCode() // 1
false.GetHashCode() // 0
public object VerySimplyCompactFastTrueBestConvertObjectToInt(object whatNeedToConvertBro, object whatTypeIsYoNeedBro)
{
var typeOfConvertingObject = whatNeedToConvertBro.GetType();
var objWhatWillBeaReturnedInOut = new object();
if ((typeOfConvertingObject == whatTypeIsYoNeedBro.GetType()) == true)
{
objWhatWillBeaReturnedInOut = Convert.GetTypeCode(whatTypeIsYoNeedBro);
}
return objWhatWillBeaReturnedInOut;
}
}
public void UpdatePhrase(PHRASE phraseColumn, bool value, string phraseId)
{
sql = string.Format("UPDATE Phrase SET {phraseColumn} = {value ? 1 : 0} WHERE PhraseId = '{phraseId}'");
App.DB.RunExecute(sql);
}
But that can be subject to SQL injection attacks, so better to write it as a parameterised query.
For scenarios needing extreme performance, you can use the System.­Runtime.­CompilerServices.­Unsafe package to perform this conversion directly inline. This will result in native code that contains no branching or function calls.
using System.Runtime.CompilerServices;
/// ...
bool _bool;
byte _byte;
_bool = true;
_byte = Unsafe.As<bool, byte>(ref _bool);
Console.WriteLine(_byte); // --> 1
_bool = false;
_byte = Unsafe.As<bool, byte>(ref _bool);
Console.WriteLine(_byte); // --> 0
You can also use this method to set up a ref local byte variable which existentially represents the instantaneous identity of the Boolean, but viewed as a byte. This might be useful for persistently monitoring a changing { false, true } using a { 0, 1 } interpretation.
class Program
{
static bool _bool;
static void Main()
{
Task.Factory.StartNew(() => { while (true) _bool = !_bool; });
// define a "ref local" that persistently views Boolean value '_bool' as a byte
ref byte _byte = ref Unsafe.As<bool, byte>(ref _bool);
while (true)
Console.Write(_byte + " ");
}
};
If you're unfamiliar with ref, with this technique just shown there is no "machinery" involved in any sort of "updating" or "conversion" whenever the value changes, because the ref byte is actually just a different "view" of the original Boolean entity itself.
The output is somewhat mesmerizing.

How to escape the "Data is null" error when the column in NULL [duplicate]

I'm using a SQLdatareader to build POCOs from a database. The code works except when it encounters a null value in the database. For example, if the FirstName column in the database contains a null value, an exception is thrown.
employee.FirstName = sqlreader.GetString(indexFirstName);
What is the best way to handle null values in this situation?
You need to check for IsDBNull:
if(!SqlReader.IsDBNull(indexFirstName))
{
employee.FirstName = sqlreader.GetString(indexFirstName);
}
That's your only reliable way to detect and handle this situation.
I wrapped those things into extension methods and tend to return a default value if the column is indeed null:
public static string SafeGetString(this SqlDataReader reader, int colIndex)
{
if(!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
Now you can call it like this:
employee.FirstName = SqlReader.SafeGetString(indexFirstName);
and you'll never have to worry about an exception or a null value again.
You should use the as operator combined with the ?? operator for default values. Value types will need to be read as nullable and given a default.
employee.FirstName = sqlreader[indexFirstName] as string;
employee.Age = sqlreader[indexAge] as int? ?? default(int);
The as operator handles the casting including the check for DBNull.
employee.FirstName = sqlreader[indexFirstName] as string;
For integers, if you cast to a nullable int, you can use GetValueOrDefault()
employee.Age = (sqlreader[indexAge] as int?).GetValueOrDefault();
or the null-coalescing operator (??).
employee.Age = (sqlreader[indexAge] as int?) ?? 0;
IsDbNull(int) is usually much slower than using methods like GetSqlDateTime and then comparing to DBNull.Value. Try these extension methods for SqlDataReader.
public static T Def<T>(this SqlDataReader r, int ord)
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return default(T);
return ((INullable)t).IsNull ? default(T) : (T)t;
}
public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return null;
return ((INullable)t).IsNull ? (T?)null : (T)t;
}
public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return null;
return ((INullable)t).IsNull ? null : (T)t;
}
Use them like this:
var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);
if(reader.IsDBNull(ColumnIndex)) {// logic} works as many answers says.
And I want to mention if you working with column names, just comparing types may be more comfortable.
if(reader["TeacherImage"].GetType() == typeof(DBNull)) { //logic }
I don't think there's a NULL column value, when rows are returned within a datareader using the column name.
If you do datareader["columnName"].ToString(); it will always give you a value that can be a empty string (String.Empty if you need to compare).
I would use the following and wouldn't worry too much:
employee.FirstName = sqlreader["columnNameForFirstName"].ToString();
You can write a Generic function to check Null and include default value when it is NULL. Call this when reading Datareader
public T CheckNull<T>(object obj)
{
return (obj == DBNull.Value ? default(T) : (T)obj);
}
When reading the Datareader use
while (dr.Read())
{
tblBPN_InTrRecon Bpn = new tblBPN_InTrRecon();
Bpn.BPN_Date = CheckNull<DateTime?>(dr["BPN_Date"]);
Bpn.Cust_Backorder_Qty = CheckNull<int?>(dr["Cust_Backorder_Qty"]);
Bpn.Cust_Min = CheckNull<int?>(dr["Cust_Min"]);
}
One way to do it is to check for db nulls:
employee.FirstName = (sqlreader.IsDBNull(indexFirstName)
? ""
: sqlreader.GetString(indexFirstName));
This Solution is less vendor-dependent and works with an SQL, OleDB, and MySQL Reader:
public static string GetStringSafe(this IDataReader reader, int colIndex)
{
return GetStringSafe(reader, colIndex, string.Empty);
}
public static string GetStringSafe(this IDataReader reader, int colIndex, string defaultValue)
{
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
else
return defaultValue;
}
public static string GetStringSafe(this IDataReader reader, string indexName)
{
return GetStringSafe(reader, reader.GetOrdinal(indexName));
}
public static string GetStringSafe(this IDataReader reader, string indexName, string defaultValue)
{
return GetStringSafe(reader, reader.GetOrdinal(indexName), defaultValue);
}
What I tend to do is replace the null values in the SELECT statement with something appropriate.
SELECT ISNULL(firstname, '') FROM people
Here I replace every null with a blank string. Your code won't throw in error in that case.
By influencing from getpsyched's answer, I created a generic method which checks column value by its name
public static T SafeGet<T>(this System.Data.SqlClient.SqlDataReader reader, string nameOfColumn)
{
var indexOfColumn = reader.GetOrdinal(nameOfColumn);
return reader.IsDBNull(indexOfColumn) ? default(T) : reader.GetFieldValue<T>(indexOfColumn);
}
Usage:
var myVariable = SafeGet<string>(reader, "NameOfColumn")
Check sqlreader.IsDBNull(indexFirstName) before you try to read it.
As an addition to the answer by marc_s, you can use a more generic extension method to get values from the SqlDataReader:
public static T SafeGet<T>(this SqlDataReader reader, int col)
{
return reader.IsDBNull(col) ? default(T) : reader.GetFieldValue<T>(col);
}
how to about creating helper methods
For String
private static string MyStringConverter(object o)
{
if (o == DBNull.Value || o == null)
return "";
return o.ToString();
}
Usage
MyStringConverter(read["indexStringValue"])
For Int
private static int MyIntonverter(object o)
{
if (o == DBNull.Value || o == null)
return 0;
return Convert.ToInt32(o);
}
Usage
MyIntonverter(read["indexIntValue"])
For Date
private static DateTime? MyDateConverter(object o)
{
return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
}
Usage
MyDateConverter(read["indexDateValue"])
Note: for DateTime declare varialbe as
DateTime? variable;
None of these was quite what i wanted:
public static T GetFieldValueOrDefault<T>(this SqlDataReader reader, string name)
{
int index = reader.GetOrdinal(name);
T value = reader.IsDBNull(index) ? default(T) : reader.GetFieldValue<T>(index);
return value;
}
I think you would want to use:
SqlReader.IsDBNull(indexFirstName)
We use a series of static methods to pull all of the values out of our data readers. So in this case we'd be calling DBUtils.GetString(sqlreader(indexFirstName)) The benefit of creating static/shared methods is that you don't have to do the same checks over and over and over...
The static method(s) would contain code to check for nulls (see other answers on this page).
You may use the conditional operator:
employee.FirstName = sqlreader["indexFirstName"] != DBNull.Value ? sqlreader[indexFirstName].ToString() : "";
There are a lot of answers here with useful info (and some wrong info) spread about, I'd like to bring it all together.
The short answer to the question is to check for DBNull - almost everyone agrees on this bit :)
Rather than using a helper method to read nullable values per SQL data type a generic method allows us to address this with a lot less code. However, you can't have a single generic method for both nullable value types and reference types, this is discussed at length in
Nullable type as a generic parameter possible? and C# generic type constraint for everything nullable.
So, following on from the answers from #ZXX and #getpsyched we end up with this, 2 methods for getting nullable values and I've added a 3rd for non-null values (it completes the set based on method naming).
public static T? GetNullableValueType<T>(this SqlDataReader sqlDataReader, string columnName) where T : struct
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.IsDBNull(columnOrdinal) ? (T?)null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
public static T GetNullableReferenceType<T>(this SqlDataReader sqlDataReader, string columnName) where T : class
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.IsDBNull(columnOrdinal) ? null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
public static T GetNonNullValue<T>(this SqlDataReader sqlDataReader, string columnName)
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
I usually use column names, alter these if you use column indexes. Based on these method names I can tell whether I'm expecting the data to be nullable or not, quite useful when looking at code written a long time ago.
Tips;
Not having nullable columns in the database avoids this issue. If you
have control over the database then columns should be non-null by
default and only nullable where necessary.
Don't cast database values
with the C# 'as' operator because if the cast is wrong it will
silently return null.
Using a default value expression will change
database nulls to non-null values for value types like int, datetime,
bit etc.
Lastly, whilst testing the above methods across all SQL Server data types I discovered you can't directly get a char[] from a SqlDataReader, if you want a char[] you will have to get a string and use ToCharArray().
I am using the code listed below to handle null cells in an Excel sheet that is read in to a datatable.
if (!reader.IsDBNull(2))
{
row["Oracle"] = (string)reader[2];
}
private static void Render(IList<ListData> list, IDataReader reader)
{
while (reader.Read())
{
listData.DownUrl = (reader.GetSchemaTable().Columns["DownUrl"] != null) ? Convert.ToString(reader["DownUrl"]) : null;
//没有这一列时,让其等于null
list.Add(listData);
}
reader.Close();
}
and / or use ternary operator with assignment:
employee.FirstName = rdr.IsDBNull(indexFirstName))?
String.Empty: rdr.GetString(indexFirstName);
replace the default (when null) value as appropriate for each property type...
This method is dependent on indexFirstName which should be the zero-based column ordinal.
if(!sqlReader.IsDBNull(indexFirstName))
{
employee.FirstName = sqlreader.GetString(indexFirstName);
}
If you don't know the column index but wan't to check a name you can use this extension method instead:
public static class DataRecordExtensions
{
public static bool HasColumn(this IDataRecord dr, string columnName)
{
for (int i=0; i < dr.FieldCount; i++)
{
if (dr.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
return true;
}
return false;
}
}
And use the method like this:
if(sqlReader.HasColumn("FirstName"))
{
employee.FirstName = sqlreader["FirstName"];
}
Old question but maybe someone still need an answer
in real i worked around this issue like that
For int :
public static object GatDataInt(string Query, string Column)
{
SqlConnection DBConn = new SqlConnection(ConnectionString);
if (DBConn.State == ConnectionState.Closed)
DBConn.Open();
SqlCommand CMD = new SqlCommand(Query, DBConn);
SqlDataReader RDR = CMD.ExecuteReader();
if (RDR.Read())
{
var Result = RDR[Column];
RDR.Close();
DBConn.Close();
return Result;
}
return 0;
}
the same for string just return "" instead of 0 as "" is empty string
so you can use it like
int TotalPoints = GatDataInt(QueryToGetTotalPoints, TotalPointColumn) as int?;
and
string Email = GatDatastring(QueryToGetEmail, EmailColumn) as string;
very flexible so you can insert any query to read any column and it'll never return with error
Here is helper class which others can use if they need based on #marc_s answer:
public static class SQLDataReaderExtensions
{
public static int SafeGetInt(this SqlDataReader dataReader, string fieldName)
{
int fieldIndex = dataReader.GetOrdinal(fieldName);
return dataReader.IsDBNull(fieldIndex) ? 0 : dataReader.GetInt32(fieldIndex);
}
public static int? SafeGetNullableInt(this SqlDataReader dataReader, string fieldName)
{
int fieldIndex = dataReader.GetOrdinal(fieldName);
return dataReader.GetValue(fieldIndex) as int?;
}
public static string SafeGetString(this SqlDataReader dataReader, string fieldName)
{
int fieldIndex = dataReader.GetOrdinal(fieldName);
return dataReader.IsDBNull(fieldIndex) ? string.Empty : dataReader.GetString(fieldIndex);
}
public static DateTime? SafeGetNullableDateTime(this SqlDataReader dataReader, string fieldName)
{
int fieldIndex = dataReader.GetOrdinal(fieldName);
return dataReader.GetValue(fieldIndex) as DateTime?;
}
public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName)
{
return SafeGetBoolean(dataReader, fieldName, false);
}
public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName, bool defaultValue)
{
int fieldIndex = dataReader.GetOrdinal(fieldName);
return dataReader.IsDBNull(fieldIndex) ? defaultValue : dataReader.GetBoolean(fieldIndex);
}
}
in c# 7.0 we can do :
var a = reader["ERateCode"] as string;
var b = reader["ERateLift"] as int?;
var c = reader["Id"] as int?;
so it will keep null value if it is.
I did my best to reimplement the Field method from DataTable. https://learn.microsoft.com/en-us/dotnet/api/system.data.datarowextensions.field
It will throw if you try to convert a DBNull.Value to a non-nullable type. Otherwise it will convert DBNull.Value to null.
I haven't fully tested it.
public static T Field<T>(this SqlDataReader sqlDataReader, string columnName)
{
int columnIndex = sqlDataReader.GetOrdinal(columnName);
if (sqlDataReader.IsDBNull(columnIndex))
{
if (default(T) != null)
{
throw new InvalidCastException("Cannot convert DBNULL value to type " + typeof(T).Name);
}
else
{
return default(T);
}
}
else
{
return sqlDataReader.GetFieldValue<T>(columnIndex);
}
}
Usage:
string fname = sqlDataReader.Field<string>("FirstName");
int? age = sqlDataReader.Field<int?>("Age");
int yearsOfExperience = sqlDataReader.Field<int?>("YearsEx") ?? 0;
Convert handles DbNull sensibly.
employee.FirstName = Convert.ToString(sqlreader.GetValue(indexFirstName));
neat one-liner:
while (dataReader.Read())
{
employee.FirstName = (!dataReader.IsDBNull(dataReader.GetOrdinal("FirstName"))) ? dataReader["FirstName"].ToString() : "";
}
you can ever check for this as well
if(null !=x && x.HasRows)
{ ....}

Invalid Cast DateTime?

I have a class with the following code
public cCase(string pCaseNo, string pMode)
{
if (pMode == "new")
{
this._caseNo = Validate_CaseNo(pCaseNo);
}
if (pMode == "existing")
{
try
{
int intValidatedCaseNo = Validate_CaseNo(pCaseNo);
string sqlText = "SELECT * FROM tblCases WHERE CaseNo = #CaseNo;";
string strConnection = cConnectionString.BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnection);
linkToDB.Open();
SqlCommand sqlCom = new SqlCommand(sqlText, linkToDB);
sqlCom.Parameters.Add("#CaseNo", SqlDbType.Int);
sqlCom.Parameters["#CaseNo"].Value = intValidatedCaseNo;
SqlDataReader caseReader = sqlCom.ExecuteReader();
if (caseReader.HasRows)
while (caseReader.Read())
{
this._claimant = caseReader["Claimant"].ToString();
this._defendant = caseReader["Defendant"].ToString();
this._caseType = caseReader["CaseType"].ToString();
this._occupation = caseReader["Occupation"].ToString();
this._doa = (DateTime?)caseReader["DOA"];
this._dateClosed = (DateTime?)caseReader["DateClosed"];
this._dateSettled = (DateTime?)caseReader["DateSettled"];
this._dateInstructed = (DateTime?)caseReader["DateInstructed"];
this._status = caseReader["Status"].ToString();
this._instructionType = caseReader["InstructionType"].ToString();
this._feeEstimate = (decimal?)caseReader["FeeEstimate"];
this._amountClaimed = (decimal?)caseReader["AmountClaimed"];
this._amountSettled = (decimal?)caseReader["AmountSettled"];
this._caseManager = caseReader["CaseManager"].ToString();
}
caseReader.Close();
linkToDB.Close();
linkToDB.Dispose();
}
catch (Exception eX)
{
throw new Exception("Error finding case" + Environment.NewLine + eX.Message);
}
}
}
However the Datetime? casts fail with an 'Invalid Cast'.
I've checked the SQL database and the field is storing valid dates
So I cant work out why, as I extract info via the DataReader into my app, the datetime fields are causing an Invalid Cast.
Please help.
You're going to want to change the line that reads:
this._doa = (DateTime?)caseReader["DOA"];
to:
if (caseReader["DOA"] != DBNull.Value)
this._doa.Value = (DateTime)caseReader["DOA"];
As well as all similar lines.
DBNull values cannot be casted from Nullable types.
Your DateTime fields probably hold a DBNull value which you cannot convert directly.
However, I'd use an extension method on your DataReader for convinience.
public static class DataReaderExtensions
{
public static DateTime? ReadNullableDateTime(this IDataReader reader, string column)
{
return reader.IsDBNull(column) ? (DateTime?)null : reader.GetDateTime(column);
}
}
// Usage
this._dateInstructed = CaseReader.ReadNullableDateTime("DateInstructed");
You should use
DateTime.TryParse Method
this not throw exception, like
var mydate =(DateTime)datetimeString
or
var mydate =DateTime.Parse(datetimeString)
does!!!
Try with the following code part
this._doa = (caseReader["DOA"] == DBNull.Value ? DBNull.Value : Convert.ToDateTime(caseReader["DOA"]);
Try to Convert Date Time as
this._doa = Convert.ToDateTime(caseReader["DOA"]);
I often deal with DBNull.Value...
So I use this method that will return the value of the object or the default value of the given value type if object's value is DBNull.Value.
public static object GetValueOrDefault(object value, Type type)
{
if (value != DBNull.Value)
return value;
if (type.IsValueType == false)
return null;
Array array = Array.CreateInstance(type, 1);
return array.GetValue(0);
}
Usage:
GetValueOrDefault(dataRecord.GetValue(fieldIndex), dataRecord.GetFieldType(fieldIndex)

How to check for NULL in MySqlDataReader by the column's name?

How can I check for a NULL value in an open MySqlDataReader?
The following doesn't work; it's always hitting the else:
if (rdr.GetString("timeOut") == null)
{
queryResult.Egresstime = "Logged in";
}
else
{
queryResult.Egresstime = rdr.GetString("timeOut");
}
rdr.IsDbNull(int i) only accepts a column number, not name.
var ordinal = rdr.GetOrdinal("timeOut");
if(rdr.IsDBNull(ordinal)) {
queryResult.Egresstime = "Logged in";
} else {
queryResult.Egresstime = rdr.GetString(ordinal);
}//if
or
if(Convert.IsDBNull(rdr["timeOut"])) {
queryResult.Egresstime = "Logged in";
} else {
queryResult.Egresstime = rdr.GetString("timeOut");
}//if
if(rdr.GetString("timeOut") == DBNull.Value)
null is not the same as DBNull
I am sorry, wrong answer, Sam B is right. I mistook this for DataRow stuff.
SqlDataReader does have strongly typed GetString() and provides IsDBNull(int column) for this case.
You must call rdr.IsDBNull(column) to determine if the value is DbNull.
You can compare the object that retrive from NULL field with DBNull.Value.
Change null to DBNull.Value.
You can also do:
If (string.IsNullOrEmpty(rdr.GetString("timeOut"))
Here's one I like:
var MyString = rdr["column"] is DBNull ? "It's null!" : rdr.GetString("column");
E.g. (for the original requirement):
queryResult.Egresstime = rdr["timeOut"] is DBNull ? "Logged in" : rdr.GetString("timeOut");
private T GetNullableValue<T>(MySqlDataReader rdr, string parameterName)
{
object value = rdr[parameterName];
if (value is DBNull)
return default;
return (T)value;
}
And the usage for example:
string message = GetNullableValue<string>(rdr, "Message");
bool flag = GetNullableValue<bool>(rdr, "Flag");
DateTime startTime = GetNullableValue<DateTime>(rdr, "StartTime");
Here is a method that I created to read DBNull and return a default(T) incase:
private T GetNullable<T>(MySqlDataReader reader, int ordinal, Func<int, T> getValue)
{
if (reader.IsDBNull(ordinal))
{
return default(T);
}
return getValue(ordinal);
}
It can be used like this:
if (reader.Read())
{
account = new Account();
account.Id = reader.GetInt32(0);
account.Name = reader.GetString(1);
account.MailVerifiedAt = GetNullable(reader, 2, reader.GetDateTime);
account.MailToken = GetNullable(reader, 3, reader.GetString);
}
The generic type T will be resolved based on the return value of the reader.- method. If it returns a string you will receive a null incase of DBNull. If it is an int it will return 0, etc.
Note: for integer values it might not be desired to get a 0 so be careful.

Convert OracleParameter.Value to Int32

I have a stored procedure call that goes like this:
using (OracleConnection con = new OracleConnection(ConfigurationManager.AppSettings["Database"]))
using (OracleCommand cmd = new OracleCommand("Package.Procedure", con))
{
Int32 existsCount;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("successCount", OracleDbType.Int32, 0, ParameterDirection.InputOutput);
cmd.Parameters.Add("BusinessId", OracleDbType.Int64, listRec.BusinessId, ParameterDirection.Input);
con.Open();
cmd.ExecuteScalar();
con.Close();
existsCount = Convert.ToInt32(cmd.Parameters["successCount"].Value);
return (existsCount);
}
But on this line:
existsCount = Convert.ToInt32(cmd.Parameters["successCount"].Value);
It throws the Exception "Unable to cast object of type 'Oracle.DataAccess.Types.OracleDecimal' to type 'System.IConvertible'."
Any thoughts? Thanks.
You can also try:
Oracle.DataAccess.Types.OracleDecimal d = (Oracle.DataAccess.Types.OracleDecimal)cmd.Parameters["successCount"].Value;
if( d.IsNull )
existsCount = 0;
else
existsCount = d.ToInt32( );
What about
existsCount = int.Parse(cmd.Parameters["successCount"].Value.ToString());
It is more efficient to use
Convert.ToInt32((decimal)(OracleDecimal)(cmd.Parameters["successCount"].Value))
I don't know the return type at runtime because the execution code is within a cross-platform data access framework under development, so I used a switch on the parameter value type to access the underlying Oracle[type].Value property for the various Oracle managed data access types.
public override object GetValue(IDataParameter parameter)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}
// https://docs.oracle.com/cd/B19306_01/win.102/b14307/OracleDbTypeEnumerationType.htm
if (parameter is OracleParameter)
{
switch (parameter.Value)
{
case OracleBinary oracleBinary:
// returns byte[]
return oracleBinary.Value;
case OracleBoolean oracleBoolean:
// returns bool
return oracleBoolean.Value;
case OracleDate oracleDate:
// returns DateTime
return oracleDate.Value;
case OracleDecimal oracleDecimal:
// oracleDecimal.Value is Decimal, so we convert to correct type.
return parameter.DbType == DbType.Decimal
? oracleDecimal.Value
: Convert.ChangeType(oracleDecimal.Value, parameter.DbType.ToType());
case OracleIntervalDS oracleIntervalDS:
// returns TimeSpan
return oracleIntervalDS.Value;
case OracleIntervalYM oracleIntervalYM:
// returns Long
return oracleIntervalYM.Value;
case OracleTimeStamp oracleTimeStamp:
// returns DateTime
return oracleTimeStamp.Value;
case OracleTimeStampLTZ oracleTimeStampLTZ:
// returns DateTime
return oracleTimeStampLTZ.Value;
case OracleTimeStampTZ oracleTimeStampTZ:
// returns DateTime
return oracleTimeStampTZ.Value;
default:
throw new NotSupportedException(
parameter.Value != null
? parameter.Value.GetType().Name
: parameter.ParameterName);
}
}
else
{
throw new NotSupportedException(parameter.GetType().Name);
}
}
In my case, I'm using Bulk Insert in Oracle, and meet the same error, let me share my solution here. I solved it by adding
oracleCommand.ArrayBindCount = datas.Count;
that is I forgot to set the ArrayBindCount property.
I suggest you convert to String, and after that you convert from String to Integer.
Dim tmpIdSesiónCalificación As String =
parametroIdSesiónCalificación.Value.ToString
_idSesiónCalificación = Convert.ToInt32(tmpIdSesiónCalificación)

Categories

Resources