What is the difference between these 2 statements? - c#

Possible Duplicate:
C# ?: Conditional Operator
statement first:
if(dr["AskingPriceFrom"]!=System.DBNull.Value)
objFilters.AskingPriceFrom=Convert.ToDecimal(dr["AskingPriceFrom"]);
else
objFilters.AskingPriceFrom=null;
statement second:
objFilters.AskingPriceFrom=Convert.ToDecimal(
dr["AskingPriceFrom"]!=System.DBNull.Value ? dr["AskingPriceFrom"] : null
);
What is difference between these two statements?
In first statement, if value is empty in if-else condition, then it stores null value correctly; but, if value is empty in the second condition, then instead of storing null value it stores 0. AskingPriceFrom is a get-set field stores decimal value. I tried to convert only dr["AskingPriceFrom"] after the question mark but the statement gives me an error.
Is there any way to protect null value from converting in decimal?

Apparently Convert.ToDecimal(null) == 0
//Edit: This should work
objFilters.AskingPriceFrom =
(dr["AskingPriceFrom"] != System.DBNull.Value) ?
Convert.ToDecimal(dr["AskingPriceFrom"]) : null;

It's because Decimal is not nullable. You should cast to decimal? so that when you convert a null to that type it will not return the default value 0 but instead return null.

in the inline version(ternary)
if it is null you will get:
objFilters.AskingPriceFrom = Convert.ToDecimal(null);
this will probably result an error.

You should read Convert.ToDecimal documentation here http://msdn.microsoft.com/en-us/library/e6440ed8.aspx.
Convert.ToDecimal returns decimal or throws exception, but in your case you need return type as Nullable<decimal>.
You can use code like this:
decimal? result;
if (Convert.IsDBNull(dr["AskingPriceFrom"]))
{
result= null;
}
else
{
result = dr.GetDecimal(reader.GetOrdinal("AskingPriceFrom"));
}

Thanks a lot to https://stackoverflow.com/users/1336654/jeppe-stig-nielsen. This is working properly.
objFilters.AskingPriceFrom = dr["AskingPriceFrom"] != System.DBNull.Value ? Convert.ToDecimal(dr["AskingPriceFrom"]) : (decimal?)null;

Related

Handling Null values in GetSQLDateTime and GetSQLMoney

AS part of an import I'm writing I'm using parameterised values, however the database i'm exporting to cannot handle NULL values, so I need to find a way to handle NULL values.
The closest I've gotten is:
if (tenantexportReader.GetSqlMoney(8).ToDecimal().Equals(null))
{
tenantimportCommand.Parameters["PRICEFINAL"].Value = "0.00";
}
else
{
tenantimportCommand.Parameters["PRICEFINAL"].Value = tenantexportReader.GetSqlMoney(8).ToDecimal();
}
and A similar thing with SQLDateTime
if (tenantexportReader.GetDateTime(9).ToShortDateString().Equals(null))
{
tenantimportCommand.Parameters["TENSDATE"].Value = "0.00";
}
else
{
tenantimportCommand.Parameters["TENSDATE"].Value = tenantexportReader.GetDateTime(9).ToShortDateString();
}
However this does not appear to work, instead I receive the following:
Message=Data is Null. This method or property cannot be called on Null values.
Instead of
if (tenantexportReader.GetSqlMoney(8).ToDecimal().Equals(null))
you should probably use
if (tenantexportReader.IsDbNull(8))
Since the value in the database is NULL (which is DbNull.Value in c#), I assume that GetSqlMoney and GetSqlDateTime throw the exception you received. DbNull.Value cannot be converted to SqlMoney or DateTime.
Check if the value is null via IsDbNull before calling GetSqlMoney or GetSqlDateTime.
So your final if statements should look something like this:
if (tenantexportReader.IsDbNull(8))
{
tenantimportCommand.Parameters["PRICEASK"].Value = "0.00";
}
else
{
tenantimportCommand.Parameters["PRICEFINAL"].Value = tenantexportReader.GetSqlMoney(8).ToDecimal();
}
Why would you assign a string to a monetary value???
Probably what you would want to do is like this:
var priceFinal = tenantexportReader.GetSqlMoney(8);
tenantimportCommand.Parameters["PRICEFINAL"].Value = (decimal)(priceFinal.IsNull ? 0 : priceFinal);
I really don't understand why you set it to "0.00" (string) when it is null and to a decimal value when it is not null.
And also for date/datetime values, again, why do you ever use string conversions and invite errors? Simply pass a date as a datetime.

Assign null to decimal using ternary operator

I am using conversion to decimal of a byte array, such that it contains either null or any other number, stored in byte. The problem here is, when I try to convert a null to Nullable decimal, it converts it to zero. I want it to remain null...
Convert.ToDecimal(obj.sal== null ? null : System.Text.Encoding.ASCII.GetString(obj.sal))
If you want the result to potentially be null, then you shouldn't be calling Convert.ToDecimal - which always returns decimal. Instead, you should use:
x = obj.sal == null ? (decimal?) null
: Convert.ToDecimal(Encoding.ASCII.GetString(obj.sal));
Note that you have to cast the null literal to decimal? - or use some other form like default(decimal?) so that the type of the second operand is decimal? - otherwise the compiler won't be able to infer the type of the conditional expression. See this question for more details on that.
Because null is of type object (effectively untyped) and you need to assign it to a typed object.
x = obj.sal == null ? (decimal?) null
: Convert.ToDecimal(Encoding.ASCII.GetString(obj.sal));

Check if decimal value is null

I would like to check if the decimal number is NULL or it has some value, since the value is assigned from database in class object:
public decimal myDecimal{ get; set; }
and then I have
myDecimal = Convert.ToDecimal(rdrSelect[23].ToString());
I am trying:
if (rdrSelect[23] != DBNull.Value)
{
myDecimal = Convert.ToDecimal(rdrSelect[23].ToString());
}
But I am getting this:
the result of the expression is always 'true' since a value of type
'decimal' is never equal to null
How can I check if that decimal number has some value?
A decimal will always have some default value. If you need to have a nullable type decimal, you can use decimal?. Then you can do myDecimal.HasValue
you can use this code
if (DecimalVariable.Equals(null))
{
//something statements
}
decimal is a value type in .NET. And value types can't be null. But if you use nullable type for your decimal, then you can check your decimal is null or not. Like myDecimal?
Nullable types are instances of the System.Nullable struct. A nullable
type can represent the normal range of values for its underlying value
type, plus an additional null value.
if (myDecimal.HasValue)
But I think in your database, if this column contains nullable values, then it shouldn't be type of decimal.
I've ran across this problem recently while trying to retrieve a null decimal from a DataTable object from db and I haven't seen this answer here. I find this easier and shorter:
var value = rdrSelect.Field<decimal?>("ColumnName") ?? 0;
This was useful in my case since i didn't have a nullable decimal in the model, but needed a quick check against one. If the db value happens to be null, it'll just assign the default value.
Assuming you are reading from a data row, what you want is:
if ( !rdrSelect.IsNull(23) )
{
//handle parsing
}
Decimal is a value type, so if you wish to check whether it has a value other than the value it was initialised with (zero) you can use the condition myDecimal != default(decimal).
Otherwise you should possibly consider the use of a nullable (decimal?) type and the use a condition such as myNullableDecimal.HasValue
If you're pulling this value directly from a SQL Database and the value is null in there, it will actually be the DBNull object rather than null. Either place a check prior to your conversion & use a default value in the event of DBNull, or replace your null check afterwards with a check on rdrSelect[23] for DBNull.
You can also create a handy utility functions to handle values from DB in cases like these.
Ex. Below is the function which gives you Nullable Decimal from object type.
public static decimal? ToNullableDecimal(object val)
{
if (val is DBNull ||
val == null)
{
return null;
}
if (val is string &&
((string)val).Length == 0)
{
return null;
}
return Convert.ToDecimal(val);
}

Using null-coalescing as a replacement for try catch block

How come I get an invalid cast exception when trying to set a NULL value returned from the database inside Comments which is of type Int32.
I am trying to replace this:
try
{
objStreamItem.Comments = (Int32)sqlReader["Comments"];
if (objStreamItem.Comments > 0) {
listComments = Comment.GetAll(objStreamItem.Id);
}
}
catch (InvalidCastException)
{
// Execute if "Comments" returns NULL
listComments = null;
objStreamItem.Comments = 0;
}
With this:
Comments = ((Int32?)sqlReader["Comments"]) ?? 0
The two are in different contexts, but you should get the idea. Instead of using a try catch block I am trying to solve this in a more elegant way.
Thanks.
UPDATE
It is stored as a nullable integer in the database.
public int? Comments
{
get;
set;
}
I just want to thank everyone who answered or posted on this question, everything was very informative. thanks!
Your SQL reader is returning DBNull when the value is null; There's no conversion from DBNull to int?, and the null-coalescing operator doesn't recognize DBNull.Value as something that needs to be coalesced.
EDIT 3
(Another problem with your original code: It will assume that "Comments" returned null if "Comments" is non-null but GetAll() throws an InvalidCastException.)
As hvd points out, you can use the as operator with nullable types:
objStreamItem.Comments = sqlReader["Comments"] as int?;
listComments = (objStreamItem.Comments ?? 0) > 0 ? Comment.GetAll(objStreamItem.ID) : null;
You could save yourself from all of this, however, if you simply defined Comment.GetAll() to return an empty list or a null reference when the ID you pass to it has no comments.
I suppose a ternary expression is the way to go here
objStreamItem.Comments = sqlReader["Comments"] is DBNull ? 0 : (Int32)sqlReader["Comments"] ;
You could also store the return value of sqlReader["Comments"] in a variable first to shorten the expression
var comments = sqlReader["Comments"];
objStreamItem.Comments = comments is DBNull ? 0 : (Int32)comments;
The ?? operator checks for null, but sqlReader["Comments"] won't ever be null. It will either be an Int32, or a DBNull. You can cast null to Int32?, but you cannot do so with DBNull.Value. You can use sqlReader["Comments"] as Int32? instead, which checks if the result can be converted to Int32, and if not, assigns null.
That statement tries to perform the cast before coalescing the values. You need to add parenthesis. Judging by your example above, it also looks like the field is an int rather than an int?:
Comments = (Int32)(sqlReader["Comments"] ?? 0);

How can I round a C# double nullable type?

I want to round a double? value so that if its value is 2.3 the result should be 2 but if the input is null then the result should be null.
There is no direct way to round a nullable double. You need to check if the variable has a value: if yes, round it; otherwise, return null.
You need to cast a bit if you do this using the conditional ?: operator:
double? result = myNullableDouble.HasValue
? (double?)Math.Round(myNullableDouble.Value)
: null;
Alternatively:
double? result = null;
if (myNullableDouble.HasValue)
{
result = Math.Round(myNullableDouble.Value);
}
As others have pointed out, it is easy enough to do this as a one-off. To do it in general:
static Func<T?, T?> LiftToNullable<T>(Func<T, T> func) where T : struct
{
return n=> n == null ? (T?) null : (T?) func(n.Value);
}
And now you can say:
var NullableRound = LiftToNullable<double>(Math.Round);
double? d = NullableRound(null);
And hey, now you can do this with any method that takes and returns a value type.
return d.HasValue ? Math.Round(d.Value) : (double?)null;

Categories

Resources