If - Strange Behavior in Detecting Type - vb.net

I discovered this strange behavior in VB.Net today in trying to work with nullable DateTime data. I am pulling a DateTime value out of an XML file for inserting into a database, and I want to allow for an empty value. So I thought I should use If to prevent casting errors:
Dim LastRun As DateTime? = _
If(rowData("LastRun") = "", Nothing, CType(rowData("LastRun"), DateTime))
It seems like this should return a value of Nothing in the case that the If is false, or a value of the date time from LastRun if the value is not blank. Instead, when the If condition returns false, I get a value of DateTime.MinValue, which causes an exception on insert to the database due to SQL DateTime underflow.
I was able to fix it by using DateTime? as the cast in the last parameter, but this behavior seems odd to me. The expected type is clearly DateTime? because that's the variable type. Also, the narrowest type that can allow for both possible result values is DateTime?, since it could be either a DateTime or Nothing. And yet somehow it decides that the result value should be DateTime and then I guess typecasts Nothing to DateTime.MinValue? What is going on here?
Part of the problem is I'm used to C#, and the equivalent expression rowData["LastRun"] == "" ? null : (DateTime)rowData["LastRun"]) doesn't even compile (as expected), because there's "no implicit conversion between DateTime and null."

Nothing is not the same as null in C#, it is a mixture between null and default(T). So when you use Nothing on a value type(like the structure DateTime) you get it's default value what is DateTime.MinValue.

Related

Fluent assertion to verify DateTime field is not empty

var dte = "2021-12-18T15:06:33.2677927Z"
dte.Should().
I want to check that this dte is not empty.
Currently I am using :
dte.Should().BeAfter(new DateTime());
From the example, your definition of an "empty" DateTime seems to be one different from the default value.
If you're looking for a more readable/idiomatic way to express that, I would go with
DateTime subject = MethodUnderTest();
subject.Should().NotBe(default);
For the general case, one cannot speak of an "empty" DateTime since even the default value is just the minimum representable valid datetime, namely 0001-01-01T00:00:00.
So all of these are identical.
DateTime.Parse("0001-01-01T00:00:00")
default(DateTime)
new DateTime()
DateTime.MinValue
DateTime.FromBinary(0)

VB why DBnull? Operator '*' is not defined for string "11106.9" and type 'DBNull'

i just want calculate amount with percent on database access.
this my code
xlWorksheet.Range("AI" & CurrentRow2).Value = Format(CDbl(strGetAccrualAllocation*ADORS_Temp1.Fields("PERCENTAGE").Value).ToString("N2"))
and this error respond
System.InvalidCastException: Operator '*' is not defined for string
"11106.9" and type 'DBNull'.
thankyou
It is always wise to check data used in a calculation for NULL. I often use the inline if to do that, for example:
IIF(IsDBNull(MyValue),0,MyValue)
If MyValue is null, zero is returned, if not, the value of MyValue is returned.
Or if you need to indicate to the user that a value is null:
If IsDBNull(MyValue) Then
'message to user that vaslue is null or some other action
Else
'perforn calculation
End If
When using a string of numeric characters, implicit conversion from string to value will take place. If there is any chance that the string could contain anything other than numeric characters, you should test for that, otherwise another error will be generated.

VB.Net is my issue with DataRow.IsNull or Format(datetimevalue,"T")?

I am working on a new ASP.Net 4.0 data driven app. In the DAL I check for NULL values on all my data and default to the proper data when NULL. I have a strange issue going on. Two dates are coming back - on one I need the time only. The First line of code for the full date works without fail - but the second line of code errors pointing to the format string but the strange part is that it errors on NULL values which does not use the format string and just returns Date.MinValue. When the second line gets data it formats the return correctly.
Dim dr As DataRow
.TourDate = IIf(dr.IsNull("tourdate"), Date.MinValue, Format(dr("tourdate"), "MM/dd/yyyy"))
.TourTime = IIf(dr.IsNull("tourtime"), Date.MinValue, Format(dr("tourtime"), "T"))
The error comes on the second line when dr("tourtime") is NULL - the erroe is: Argument 'Expression' is not a valid value.
IIf in VB.Net does not do short-circuit evaluation, so the Format call is being executed even if the value is null.
You need to use If:
.TourTime = If(dr.IsNull("tourtime"), Date.MinValue, Format(dr("tourtime"), "T"))
This is the same issue described here: Using VB.NET IIF I get NullReferenceException
To trouble-shoot this, I would inspect the actual value stored. A datetime column that appears to be null may actually have a value.
I think you should use IsDbNull instead of IsNull.

Why does an uninitialised DateTime struct tell me it's monday

I have a DateTime struct I use, and sombody commented out the part where it was created (but not declared) When I was using it, myDate.DayOfWeek == DayOfWeek.Monday returned true.
If the part where it is created is commented out, how can it tell me it's monday, instead of throwing some exception?
DateTime is a value type (a struct), and therefore it always has a value. It cannot be null like a reference type. When a variable of a value type is not assigned yet, it's initialized to some default value depending on the type. The default value for DateTime just happens to be a Monday in the calendar .NET uses.
Of course, calendars have changed many times in the past and applying our current calendar more than a few hundred years into the past just doesn't work, but to .NET, it's a Monday.
DateTime is a struct which means that it has to have some sort of default value. The default value for DateTime is DateTime.MinValue, which is 1 January 0001, which was a monday.

InvalidCastException when parsing dates in VB.NET

I'm trying to Parse dates entered into a TextBox into a DateTime value but I keep getting an exception in the TryParseExact method. What I'm trying to do is:
DateTime.TryParseExact(tbAddDate.Text.Trim, "yyMMdd", New CultureInfo("sv-SE"), DateTimeStyles.None, row.Date)
This throws an InvalidCastException with the message "Conversion from type 'DBNull' to type 'Date' is not valid." I realize what is happening is that it's trying to set row.Date to DBNull which is not a valid value for a DateTime. What I don't understand is why it's trying to do this, as the documentation states that it should be set to MinValue and not DBNull.
As a sidenote, I know that I can get around a lot of these problems by using a DateTimePicker but the customer feels that they are very clunky as it's not possible to enter the dates directly with the keyboard.
It seems that (as magnifico's comment suggests) the problem is strictly related to the fact you're passing row.Date as the result argument. It must occur when the code attempts to assign row.Date with Date.MinValue (unless the documentation is inaccurate, which is less likely in this scenario).
I'd advise that you pass some different result argument, and use its value to update row.Date after calling TryParseExact. It might not be the ultimate permanent solution, but it should help you inspect this bug and find the cause to the InvalidCast exception.
Sidenote: perhaps this row.Date doesn't accept Date.MinValue as a legitimate value, i.e.: row.Date might be willing to accept only dates from 01/01/2000 onwards, and Date.MinValue returns 01/01/0001.