C# How to check is there any value before converting ToString() - c#

I have a dataset of values, which I need to put into a textbox. However, there are some decimal and double type values in my dataset, so I need to cast them toString(). Furthermore, sometimes the dataset values are empty, so before casting toString() I need to check whether there is actually a value there or not.
This is sample line:
I need code that does something like this...
if(ds.Tables[0].Rows[0].Field<decimal>("IndexPrethodni") !=null or something){
Convert.ToString(ds.Tables[0].Rows[0].Field<decimal>("IndexPrethodni"));
}
I known decimal is not a nullable type. Is there any easy solution to achieve my desired result?

Personally, I'd wrap it like so:
var col = ds.Tables[0].Columns["IndexPrethodni"];
var row = ds.Tables[0].Rows[0];
if (!row.IsNull(col))
{
string s = row[col].ToString();
...
}
(the "via a column object" is the most direct (= fastest) indexer)

Try
if(ds.Tables[0].Rows[0]["IndexPrethodni"] != DBNull.Value)
You can also check the value using Convert.IsDBNull().

I normally use a method such like:
public T GetValue<T>(object source)
{
if (Convert.IsDBNull(source))
return default(T);
return (T)source;
}
E.g.
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
return GetValue<string>(reader["SomeColumn"]);
}
}

check for DBNull
if(ds.Tables[0].Rows[0].Field("IndexPrethodni") != DBNull.Value) {
//convert to string
}

TO use Convert.ToString you need not to check for null value, because if there will null then also it will not give any error and return blank..

You need to check the value isnt DBNull, so something like this would work
object columnValue = ds.Tables[0].Rows[0].Field<decimal>("IndexPrethodni");
if (object != System.DBNull.Value) Convert.ToString(columnValue);

Why don't you use the nullable type to check for a value?
if( ds.Tables[ 0 ].Rows[ 0 ].Field<decimal?>( "IndexPrethodni" ).HasValue )
{
Convert.ToString( ds.Tables[ 0 ].Rows[ 0 ].Field<decimal>( "IndexPrethodni" ) );
}

If we are checking for decimal value is null or not before converting to other type
decimal? d;
if (!d.HasValue)
{
//d is null
}

Related

Cast to int on SqlCommand-ExecuteScalar error handling

I have code that is possibly fragile. This statement here
int countDis = (int)cmd.ExecuteScalar();
If I change the stored procedure to not return ANYTHING, then that casting to (int) is going to blow up. If I simply remove it, then I cannot compile.
What is the best code practice for defensive coding in this situation?
Just change the code as:
int countDis = Convert.ToInt32(cmd.ExecuteScalar());
This will ensure that even if ExecuteScalar returns null, as result of not selecting anything in stored procedure, countDis will have a value of 0. Because Convert.ToInt32(null) = 0.
Update (10/12/2018)
Safer version. Thanks #Moe for highlighting DBNull case.
object result = cmd.ExecuteScalar();
result = (result == DBNull.Value) ? null : result;
int countDis = Convert.ToInt32(result);
I usually use nullable types. e.g. :
string str;
int? countDis = cmd.ExecuteScalar() as int?;
if (countDis == null)
str = "count is null";
else
str = "Count is : " + countDis.Value;
This will work for whether ExecuteScalar returns null or DBNull.Value.
You can check the scalar value before cast.
var result = cmd.ExecuteScalar();
int countDis =result != null ? int.Parse(result) : 0;
Because ExecuteScalar can return DBNull, the best way there I found is:
var result = cmd.ExecuteScalar();
int countDis = result != null ? Convert.ToInt32(result) : 0;
if you treat a result of DBNull.Value as the same as null in that they should both be 0, you can use a single line, though you're still using a temporary variable. I won't speak of execution speed:
int countDis = int.TryParse(cmd.ExecuteScalar()?.ToString(), out int temp) ? temp : 0
You can use to get as Object, and check its type then take your decision:
object obj = cmd.ExecuteScalar();
if (obj.GetType() == typeof(string))
{
//you can do your stuff with STRING
}
else if (obj.GetType() == typeof(int))
{
//you can do your stuff with INT
}
else
{
//add here ANYOTHER type you many want in future...
}

Im having an error Object cannot be cast from DBNull to other types

I have an error on return Convert.ToInt32(dataGridView1[0, Row].Value); it says that 'Object cannot be cast from DBNull to other types.' My database field on student ID is int. Here is my code:
public int GetStudentID()
{
// The Student ID is the first cell of the current row
int Row = dataGridView1.CurrentRow.Index;
return Convert.ToInt32(dataGridView1[0, Row].Value);
}
public string GetISBN()
{
// The ISBN is the second cell of the current row
int Row = dataGridView1.CurrentRow.Index;
return dataGridView1[1, Row].Value.ToString();
}
There a two possible problems here:
You are getting nulls from the database but always expecting a value
You are getting nulls from the database but not handling them
For problem 1, ensure the query that you're executing cannot allow null values. Maybe you're missing a filter...?
For problem 2, you need to check for null values:
public int GetStudentID()
{
int Row = dataGridView1.CurrentRow.Index;
var val = dataGridView1[0, Row].Value;
if (object.Equals(val, DBNull.Value))
{
/* either throw a more appropriate exception or return a default value */
// let's assume a default value is fine
return -1;
}
return Convert.ToInt32(val);
}
Your dataGridView1[0, Row].Value must be NULL
Check for NULL or use a try-catch block with NullReferenceException like below
try
{
return Convert.ToInt32(dataGridView1[0, Row].Value);
}
catch(NullReferenceException e)
{
return 0;//No such student ID when NULL is encountered.
}
You should check for DBNull.Value. It is not the same as null.
if(DBNull.Value != dataGridView1[0, Row].Value)
{
// do convertion, etc
}
else
{
// handle null case
}
It's handy to have a method to manage this little detail, e.g.:
email = Database.GetValueOrNull<string>(sqlCommand.Parameters["#Email"].Value);
Implemented like this:
public static T GetValueOrNull<T>(Object column)
{
// Convert DBNull values to null values for nullable value types, e.g. int? , and strings.
// NB: The default value for non-nullable value types is usually some form of zero.
// The default value for string is null .
// Sadly, there does not appear to be a suitable constraint ("where" clause) that will allow compile-time validation of the specified type <T>.
Debug.Assert(Nullable.GetUnderlyingType(typeof(T)) != null || typeof(T) == typeof(string), "Nullable or string types should be used.");
if (!column.Equals(DBNull.Value)) // Don't trust == when the compiler cannot tell if type <T> is a class.
return (T)column;
return default(T); // The default value for a type may be null . It depends on the type.
}
Moving data from a variable to a database parameter with null conversion may be accomplished thusly:
sqlCommand.Parameters.AddWithValue("#Serial", serial ?? (object)DBNull.Value);

C# ?? null coalescing operator LINQ

I am trying to prevent having NULL values when I parse an XML file to a custom object using LINQ.
I found a great solution for this on Scott Gu's blog, but for some reason it does not work for integers with me. I think I have used the same syntax but it seems I am missing something. Oh and for some reason it works when the node is not empty.
Below is an extract of my code.
List<GrantAgresso> lsResult = (from g in xml.Element("root").Elements("Elementname")
select new GrantAgresso()
{
Year = (int?)g.Element("yearnode") ?? 0,
Subdomain = (string)g.Element("domainnode") ?? ""
}).ToList();
The errormessage is:
Input string was not in a correct format.
If anyone has a clue as to what I'm doing wrong, please help :)
Edit: piece of XML (strange names but it's not by choice)
<Agresso>
<AgressoQE>
<r3dim_value>2012</r3dim_value>
<r0r0r0dim_value>L5</r0r0r0dim_value>
<r7_x0023_province_x0023_69_x0023_V005>0</r7_x0023_province_x0023_69_x0023_V005>
<r7_x0023_postal_code_x0023_68_x0023_V004 />
<r7_x0023_country_x0023_67_x0023_V003>1004</r7_x0023_country_x0023_67_x0023_V003>
<r7_x0023_communitydistrict_x0023_70_x0023_V006>0</r7_x0023_communitydistrict_x0023_70_x0023_V006>
</AgressoQE>
</Agresso>
It is this expression which is throwing:
(int?)g.Element("yearnode")
That's because if the actual value of the element's text node is String.Empty and not null, since the empty string is not a valid format for Int32.Parse, the attempted cast fails.
If the element is missing completely from your XML, this works as you expect, but if there is an empty tag <yearnode/> or <yearnode></yearnode>, you'll get the exception.
The following extension method will return 0 both if the element is not present, the element is empty or it contains a string that cannot be parsed to integer:
public static int ToInt(this XElement x, string name)
{
int value;
XElement e = x.Element(name);
if (e == null)
return 0;
else if (int.TryParse(e.Value, out value))
return value;
else return 0;
}
You could use it like this:
...
Year = g.ToInt("r3dim_value"),
...
Or if you're ready to consider the cost of reflection and to accept the default value of any value type, you may use this extension method:
public static T Cast<T>(this XElement x, string name) where T : struct
{
XElement e = x.Element(name);
if (e == null)
return default(T);
else
{
Type t = typeof(T);
MethodInfo mi = t.GetMethod("TryParse",
BindingFlags.Public | BindingFlags.Static,
Type.DefaultBinder,
new Type[] { typeof(string),
t.MakeByRefType() },
null);
var paramList = new object[] { e.Value, null };
mi.Invoke(null, paramList);
return (T)paramList[1]; //returns default(T), if couldn't parse
}
}
and use it:
...
Year = g.Cast<int>("r3dim_value"),
...
You can add Where operator
.....
.Where(a => ! string.IsNullOrEmpty(a)).ToList();
If year is null or empty string that you will get an "Input string was not in a correct format" exception. You may write an extension method to read values. I haven't tested code below, but it may give you some hints.
public static ReadAs<T>(this XElement el, T defaultValue) {
var v = (string)el; // cast string to see if it is empty
if (string.IsNullOrEmpty(v)) // test
return defaultValue;
return (T)el; // recast to our type.
}
The message Input string was not in a correct format looks like the one thrown by int.parse () so it could be that you have a yearnode with a value (not null) but which cannot be successfully parsed to an integer value.
Something like this may fix it:
List<GrantAgresso> lsResult = (from g in xml.Element("root").Elements("Elementname")
let yearNode = g.Element("yearnode")
select new GrantAgresso
{
Year = string.IsNullOrWhiteSpace(yearNode.Value) ? 0 : int.Parse(yearNode.Value),
Subdomain = g.Element("domainnode").Value
}).ToList();
A couple of things to note:
select new GrantAgresso - you don't need parenthesis for a default constructor with object initializers.
string.IsNullOrWhiteSpace - was introduced in .net 4.0, use string.IsNullOrEmpty if you're on 3.5 or earlier
g.Element("domainnode").Value - will always return a string
if you want a null for Year instead of 0, use (int?)null instead of 0
Your problem is that the cast from XElement to int? uses int.Parse method on the string value of the XElement, which in your case is String.Empty. The following results in the same error:
XElement x = new XElement("yearnode", String.Empty);
int? a = (int?)x; // throws FormatException
You can avoid this by first casting the XElement to string and checking if it is null or empty and only if not doing the cast to int?. To do this, replace
Year = (int?)g.Element("yearnode") ?? 0,
with
Year = !string.IsNullOrEmpty((string)g.Element("yearnode")) ? (int?)g.Element("yearnode") : 0,
Its not pretty and will still throw if the string is otherwise not legal, but it works if you can assume that the element is always an integer or null/empty.

How to safely cast nullable result from sqlreader to int?

I have a table which contains null values and I need to get data from the table using SqlDataReader. I can't figure out how I can safely cast DBNull to int.
I'm doing it in this way at the moment:
...
reader = command.ExecuteReader();
while (reader.Read()) {
int y = (reader["PublicationYear"] != null) ? Convert.ToInt32(reader["PublicationYear"]) : 0;
...
}
...
but getting a Object cannot be cast from DBNull to other types. when PublicationYear is null.
How can I get the value safely?
Thanks.
You should compare reader["PublicationYear"] to DBNull.Value, not null.
DBNull is not the same as null. You should try something like this instead:
int y = (reader["PublicationYear"] != DBNull.Value) ? ...
int ord = reader.GetOrdinal("PublicationYear");
int y = reader.IsDBNull(ord) ? 0 : reader.GetInt32(ord);
Or, alternatively:
object obj = reader["PublicationYear"];
int y = Convert.IsDBNull(obj) ? 0 : (int)obj;
You should explicitly check if the value returned is of type DBNull
while (reader.Read()) {
int y = (!reader["PublicationYear"] is DBNull) ? Convert.ToInt32(reader["PublicationYear"]) : 0;
...
}
In fact, you can do this comparison by value as well as type:
reader["PublicationYear"] != DBNull.Value
In short - you can expect DBNull to be returned for nulls from the database, rather than null itself.
as an alternative you can do the following.
as you are converting DBNull to 0, alter the procedure that does the select. so that the select itself returns zero for a null value.
snippet to demonstrate the idea
SELECT ...
,ISNULL (PublicationYear, 0) as PublicationYear
...
FROM sometable
advantage of this is that, no additional checking is needed in your code.
Change
reader["PublicationYear"] != null
to
reader["PublicationYear"] != DBNull.Value
That's the error: (reader["PublicationYear"] != null)
You should test for DBNull.Value....
Change your test from (reader["PublicationYear"] != null) to (reader["PublicationYear"] != DBNull.Value).
Database null values should be compared with DBNull.Value:
reader = command.ExecuteReader();
while (reader.Read())
{
int y = (reader["PublicationYear"] != DBNull.Value) ? Convert.ToInt32(reader["PublicationYear"]) : 0;
...
}

C# DataTable ItemArray returns '{}' - how can I test for null value?

I have a DataTable resultSet; - I'm trying to check fields for null, but get an '{}' (empty-set ?) object back. Searches involving "{}" aren't yielding any appropriate solutions.
This is the code that isn't working as expected when the "fk_id" field is null:
if (resultSet.Rows[0].ItemArray[resultSet.Columns.IndexOf("fk_id")] == null)
{
//never reaches here
}
Note: using an int index instead of the Columns.IndexOf() isn't the issue.
Also does the "{}" have some other name in C#?
To check a column for DBNull in a DataSet, you can use the IsNull method:
if (resultSet.Rows[0].IsNull("fk_id"))
Your comparison against null is probably failing because DataSets don't use null to represent a "database NULL" value - they use DBNull.Value. If you need your code to work the way you've presented it, try this:
if (resultSet.Rows[0].ItemArray[resultSet.Columns.IndexOf("fk_id")] == DBNull.Value)
try
{
if (DT.Rows[0][0] != null)
{
//your code
}
}
catch
{
MessageBox.Show("AUTHANICATION FAILED.");
}
Please use:
dataTable.Select("FieldName is NULL")
this will give you the DataRows with null values in FieldName column.

Categories

Resources