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);
Related
I am trying to cast a null boolean from the database using this method:
bool? primaryFlag = reader["primaryflag"] is DBNull ? null: (bool?)reader["primaryflag"];
I keep getting a Specified Cast Invalid Exception. What is wrong with the method I'm using?
You cannot cast it to a Nullable<bool> directly. But you can use the as operator:
bool? primaryFlag = reader["primaryflag"] as bool?;
This works because the cast fails if the value is DBNull.Value, so it will correctly assign a bool? that is null.
or this less elegant version:
bool? primaryFlag = null;
int colOrdinal = reader.GetOrdinal("primaryflag");
if(!reader.IsDBNull(colOrdinal))
primaryFlag = reader.GetBoolean(colOrdinal);
The problem is that the value in the reader is never a bool?.
Of course, if you cast to a bool, you'll get an error on your ternary, because there's no common type that the compiler can infer. I use a simple trick instead:
reader["primaryFlag"] is DBNull ? default(bool?) : (bool)reader["primaryFlag"];
default(bool?) means exactly the same thing as null in runtime, but it makes the null "typed", as far as the compiler is concerned.
It's also pretty handy to have this as an extension method, so you can just do something like
reader.GetNullable<bool>("primaryFlag")
There a 2 logical solutions:
1 is casting the DB value to the desired task:
bool? primaryFlag = (bool?)reader["primaryflag"]
2 is more simular to you approach:
bool? primaryFlag = reader["primaryflag"] is DBNull ? (bool?) null: (bool)reader["primaryflag"];
You have to also cast the null value with (bool?) null.
When i give empty value to bank region and cost centre it gives the error during saving to database.
Error:input string was not in a correct format.
objMEndorsement.BankRegion = Convert.ToInt32(txtBankRegion.Text);
objMEndorsement.CostCenter = Convert.ToInt32(txtCostCenter.Text);
this is the code i used.How i will save empty textbox value to database.
Try something like this:
objMEndorsement.BankRegion = string.IsNullOrWhiteSpace(txtBankRegion.Text) ? 0 : Convert.ToInt32(txtBankRegion.Text)
Replace
objMEndorsement.BankRegion = Convert.ToInt32(txtBankRegion.Text);
objMEndorsement.CostCenter = Convert.ToInt32(txtCostCenter.Text);
by
objMEndorsement.BankRegion = Convert.ToInt32(txtBankRegion.Text??0);
objMEndorsement.CostCenter = Convert.ToInt32(txtCostCenter.Text??0);
?? is null coalesce operator in c#
EDIT:
Best option would be to use tryParse like this
bool isInteger=int.TryParse(txtBankRegion.Text??0, out num1);
if(isInteger)
{
//insert into database
}
Try to use int.TryParse() this is better in handling conversion.
You can do it this way:
int bankRegion = 0; //Default value if wasn't able to parse
int.TryParse( txtBankRegion.Text, out value );
objMEndorsement.BankRegion = bankRegion;
Then you can do the same with the other field.
Make objMEndorsement.BankRegion NULLable and:
if(!string.IsNullOrWhiteSpace(txtBankRegion.Text))
objMEndorsement.BankRegion = Convert.ToInt32(txtBankRegion.Text)
(This works if NULL is the initial value of the property objMEndorsement.BankRegion = Convert.ToInt32(txtBankRegion.Text))
Otherwise (property still have to accept NULL):
objMEndorsement.BankRegion = string.IsNullOrWhiteSpace(txtBankRegion.Text) ? null : Convert.ToInt32(txtBankRegion.Text);
Remember that your database field must be NULLable also (otherwise you will get a DB error when trying to persist NULL).
make it nullable type by converting the value type to nullable type and then send it to database
yes use ternary operator and assign corresponding values
objMEndorsement.BankRegion = (txtBankRegion.Text.trim()) ? 0 : Convert.ToInt32(txtBankRegion.Text)
Something like the ternary operator (?:) or the null coalescing operator (??). It seems silly to me to take up two lines and be so wordy when the other operators exist.
EDIT:
Since it's requested, here's two possible examples of what I hope that I can find
var variable ?= mightBeNull;
or
var variable = mightBeNull != null ? mightBeNull
Really, it's either something that can be used to assign a value, if it's not null, to a variable or an If without an Else packaged nicely in an operator.
The ??= operator is coming to C# 8.
int? i = null; // i = null
i ??= 0; // i = 0
i ??= 1; // i = 0
// different ways of writing 'i ??= 0;':
i = i ?? 0;
if (i == null) i = 0;
So you want this?
if (other != null)
someVariable = other;
You could do the following, but I'd argue that the above is better due to clarity and possible side effects:
someVariable = other ?? someVariable;
The above might cause side effects if someVariable is a property and either the get or set can cause side effects; this shouldn't be important if your property follows the ordinary guidelines. Or, as Servy points out, even if it's a field, it could created different semantics in a multithreaded app. I should note that in the first example, you read other twice, which also has the potential for complexity to enter (though a smaller potential than the latter example).
I bet this is what you are looking for.
Let's say we have a function, myFunction that says whether the argument passed input is null or not. If input is null, it will return "Input is null!", else it will return "Input is not null".
This is the normal approach:
public String myFunction(string input) {
if (input == null)
return "Input is null!";
else
return "Input is not null";
}
And this is the other approach (What you are looking for):
public String myFunction(string input) {
return (input == null) ? "Input is null!" : "Input is not null";
}
It is called (?: conditional operator).
To assign a value to a variable only if it is not null, you would need to use an if. Neither the conditinal nor the null coalesce operators would do that.
if(somethingElse != null) something = somethingElse;
There is no specific operator in C# that does exactly this.
In Visual Studio 2015 C# there is a new operator called the Null-Conditional that does what you are asking. It is the ?. or ? operator.
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
int? count = customers?[0]?.Orders?.Count(); // null if customers, the first customer, or Orders is null
Currently useable in previous versions of C# but not an operator but rather a one liner would be to use the ? : statement
?: operator
condition ? first_expression : second_expression;
AssingningTO = (someVar == null) ? null: someVar; // if null assign null ELSE assign someVar
AssingningTO = (someVar == null) ? String.Empth(): someVar; // if null assign empty string else someVar
Nullable types can represent all the values of an underlying type, and an additional null value.
http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Can someone comment on the issue I'm having. A ternary operator throws an error and the argument here is that if it evaluates to null then it should ignore the part after the colon. The Watch set up for this indicates an exception:
Int32.Parse(SQLDataReader["TrayId"].ToString())' threw an exception of Type 'System.FormatException
suggesting that it can't convert a null to a string. Is this how it works?
ShipmentId = SQLDataReader["ShipmentId"] == DBNull.Value ? 0 : Int32.Parse(SQLDataReader["ShipmentId"].ToString()),
The column ShipmentId is an integer, but it is also nullable, which means that the c# type is int?.
The error boils down to this code:
Int32.Parse((string)null)
The parsing gives up because you can't turn null into an int.
To fix this, use TryParse.
int ShipmentId = 0;
int.TryParse(SQLDataReader["ShipmentId"].ToString(), out ShipmentId);
This will cover if the value is null, or if for some strange reason the value can't actually be converted to an int (like "asdf121343fds").
It's recommended that for comparisons with DBNull, you use the DBNull.Value.Equals method, as described on this page: http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx
ShipmentId = DBNull.Value.Equals(SQLDataReader["ShipmentId"]) ? 0 : Int32.Parse(SQLDataReader["ShipmentId"].ToString());
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;