I have to modify a Visual Studio 2010 C# project that works with Oracle, looking at some code I've found a function that returns a List<> with values loaded from a database stored procedure (cursor)
while (myIDataReader.Read())
{
// OK
myTable.myStringField = myIDataReader["TableStringField"].ToString();
// ¿?
myTable.myIntField =
Convert.ToInt32((myIDataReader["TableIntField"] == DBNull.Value) ? null : myIDataReader["myTableField"]);
}
Everything's ok, just want to know, what conditions are given when assign myTable.myIntField, I know this column is nullable, but I don't get the syntax, if someone can explain I'll be thankful
You are talking about this line?
myTable.myIntField =
Convert.ToInt32((myIDataReader["TableIntField"] == DBNull.Value) ? null : myIDataReader["myTableField"]);
If you break that statement apart, you have a type of conditional, often called the Ternary operator, explained here.
conditional ? if_true_do_this : if_false_do_this
It is really just a different syntax for:
if(conditional) {
if_true_do_this;
} else {
if_false_do_this
}
After that, it simply passes the result to Convert.ToInt32() to turn it from a string into an int.
So that line of code is just a more concise version of this:
if(myIDataReader["TableIntField"] == DBNull.Value)
{
myTable.myIntField = Convert.ToInt32(null);
}
else
{
myTable.myIntField = Convert.ToInt32(myIDataReader["myTableField"]);
}
The syntax above works correctly and it means:
TableIntField could contains a database null.
This is expressed in NET via the DBNull object and its Value field.
The code checks if the TableIntField contains the DBNull.Value via C# ternary operator.
If the checks result in a true condition, a null is used as argument for Convert.ToInt32 and this, according to MSDN documentation, result in a zero value assigned to myTable.myIntField.
Related
I've got the following code:
// Here is where we will read in all our values and populate the form with them
lblBenCatX.Text = Convert.ToString(reader["Category"]);
lblBenProvX.Text = Convert.ToString(reader["Provision"]);
txtCommentBox.Text = Convert.ToString(reader["Feedback"]);
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
ddlIssue1.SelectedValue = Convert.ToString(reader["Issue_ID"]);
ddlResolution1.SelectedValue = Convert.ToString(reader["Resolution_ID"]);
ddlDefect2.SelectedValue = Convert.ToString(reader["Network2"]);
ddlIssue2.SelectedValue = Convert.ToString(reader["Issue_ID2"]);
ddlResolution2.SelectedValue = Convert.ToString(reader["Resolution_ID2"]);
The first 3 rows of code; no problem. However, if I have a record with a NULL value, the dropdowns break the code. So, I'm thinking I need to check the field first to make sure it's not NULL. Something like:
if (!Convert.ToString(reader["Network"]) = NULL)
{
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
}
However, that's giving me an error:
The left-hand side of an assignment must be a variable, property or
indexer
Any ideas? This is C# in VS2015 with an Oracle back end, if any of that matters.
In C#, you need to use two equal signs in a row == for equality comparison, not one. One equal sign = is an assignment operator.
if (first == second) { ... }
In your case, though, you would want to use the "not equals" != operator:
if (Convert.ToString(reader["Network"]) != null)
Which is cleaner and slightly more-efficent than this:
if (!(Convert.ToString(reader["Network"]) == null))
Note that I've wrapped the whole inner comparison in parens so the whole statement is being negated; otherwise, it will think you're trying to say !Convert.ToString(reader["Network"]), and, as you pointed out in the comments here, you can't use ! with a string.
That being said, if you're converting to string, then it's better to use string.IsNullOrEmpty() for checking:
if (!string.IsNullOrEmpty(reader["Network"].ToString())))
But the best is probably to just check if the column value is null, rather than converting it to string:
if (!reader.IsDBNull(["Network"]))
= is an assignment operator, used when setting values.
== is an equality operator, which determines whether something is equal to something else.
!= is also an equality operator, opposite to the one above. So, when something is not equal to something else.
So actually, you should be using != in this scenario:
if (Convert.ToString(reader["Network"]) != null)
{
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
}
You have a couple of choices. The first is to check if the value is DBNull which is different than an empty string/null value.
if (!reader.IsDBNull([ordinalPositionOfNetworkInSelectStatement]))
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
See IDataReader.IsDBNull. The only thing is that you need to know the ordinal position of the column you are checking.
The alternative is to check for dbnull in your sql select statement and use a function to return an empty string if it is. The positive side of this approach is you do not have to worry about checking for null in your c# code but I am not sure if it has any negative consequences in your oracle query or view. You can do this with COALESCE.
SELECT Category, Provision, Feedback, COALESCE(Network, '') AS Network /*other columns*/
FROM ... -- rest of the query
disclaimer - my oracle syntax is lacking but COALESCE does exist as a function
My C# code-behind looks like this:
if ((DT["BENEFIT_TYPE1"].Equals(0)))
{ DropDownList_Tracking_BenefitType1.SelectedValue = null; }
else if ((DT["BENEFIT_TYPE1"].ToString() = "" ))
{ DropDownList_Tracking_BenefitType1.SelectedValue = null; }
else
{DropDownList_Tracking_BenefitType1.SelectedValue = (DT["BENEFIT_TYPE1"].ToString());}
The code doesn't like the "else if" line; everything inside the parens is underlined in red. When I hover my mouse over it, the popup message is:
The left-hand side of an assignment must be a variable, property or
indexer
Can someone tell me how to fix this? I'm trying to account for NULL values in my dataset.
As Juan pointed out, you need ==, however note that NULL and "" are different things.
You can check for null or empty with:
else if (string.IsNullOrEmpty(DT["BENEFIT_TYPE1"].ToString()))
You are missing a '=' character. In C# comparisions are done with double equal sign '=='. A single one means assignment, hence your error as you cannot assign in a if statement.
Try:
(DT["BENEFIT_TYPE1"].ToString() == "" ))
As other have suggested there are other things to take into account here.
For checking strings to be null or empty you can use the following:
string.IsNullOrEmpty(yourString)
Or if you treat empty space string as empty
string.IsNullOrWhitespace(yourString)
If DT is a datatable that you are sourcing from Database the nulls in database are not null or empty string but DbNull, so you should compare this way:
DT["field"] == DbNull.Value
Or
DT.IsNull("field")
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.
this is related to comparing values in C#.
basically by default, in C# till date i only used forward comparison as follows:
string value1 = "";
if (value1 == null)
{
Console.WriteLine("True");
}
else
{
Console.WriteLine("False");
}
somewhere on Internet, i came across a link where it is said that while comparing values in C#, we should prefer Reverse Comparison as :
string value1 = "";
if (null == value1)
{
Console.WriteLine("True");
}
else
{
Console.WriteLine("False");
}
Now the problem is that is there any basic difference between the two ways of comparing values or not (i.e. both are same).
Looking for favorable replies.
Thanks
This is a hangover from languages where values are implicitly converted to a boolean type.
For the most part, anything that was non-null or non-0 would be treated as true, otherwise it was equivalent to false. This meant that any assignation of a constant would always be true.
This thing to remember here is that the assignment function returns the value assigned, much in the same way that 5 is the result of 2+3, myInt = 5 also returns 5.
Because of this, it was recommended that you check the variable against the constant. The null example is actually probably a bit contrived in this case, as it would, in most languages, return as false.
As an example:
if(i = 1)
{
printf("Always out\n");
}
else
{
printf("Never prints\n");
}
i is assigned the value of 1, which then returns the value of the assignment, 1, to the if statement. This is equivalent to true, and the if condition matches.
If you were to attempt to assign i to the constant 1, you wouldn't compile, and so it was recommended that you do things it that order (e.g. 1 == i).
This is not neccesary in C#, and further to your example, the recommended practice is to call if(String.IsNullOrEmpty(myStringValue)) { //.... }, as a string has... two ... default values from a semantic perspective.
Reverse comparison protects you from errors, when you use == (compare) instead of = (assign). But complier also warns you if you do this.
I'm used to using VB.net for web programming.
Often, I have something like:
Dim s as string = Session("s")
I get a string value for s from the web session. If there is no value in the web session, I get a blank string.
However, AFAIK, in C#, I have to have something like the code below to do the same thing.
string s;
try { s = Session["s"].ToString(); }
catch { s = ""; }
Is there an easier way to do this?
This is a quick way of doing this:
s = (string)Session["s"] ?? "";
This will cast Session["s"] to a string, and if it is not null, return the value. If it is null, it will return an empty string. The "a ?? b" expression is essentially the same as "a != null ? a:b" (?? is compiled more efficiently though)
Something else to keep in mind: you should never use exceptions for normal application logic.
Because string is reference type then is nullable, so you can check for empty or null by means of string.IsNullOrEmpty(s):
string s = string.IsNullOrEmpty((string)strObject) ? string.Empty : strObject.ToString();
Otherwise (as Philippe Leybaert says) you can use ?? operator.
I almost agree to Philippe, but it only works if "s" is present in the session, otherwise there will be a KeyNotFoundException. This code checks it, but does not solve the NULL issue of Philippe.
s= Session.ContainsKey("s")?Session["s"]:"";
So to cover both possibilities, it becomes mre complex:
s = Session.ContainsKey("s")?(Session["s"]??""):"";
It does not really make it easier, but the performance should be better than catching an exception.