I'm trying to reuse the same code I've always used but now it is encountering an error.
I'm looping through various user tables, and in there I do this:
DateTime dcdt = (DateTime)u.DateCreated;
DateTime lldt = (DateTime)u.LastLogon;
userRow["DateCreated"] = dcdt.ToShortDateString();
inside the loop. I get the error:
System.InvalidOperationException: Nullable object must have a value.
The error highlights "lldt" line, instead of "dcdt" which comes first. That is strange in and of itself. Both these fields in the database "allow nulls" is checked. And they both could be null or neither might be null.
The two values are both listed as DateTime? types through intellisense.
I don't understand why ASP.NET refuses to allow me to output blank for null dates. If it is empty/null, then logic would suggest that ASP.NET should just print nothing.
How else am I suppose to output null dates? I tried adding if statements to prevent trying to cast null DateTimes, but it doesn't help, it makes no sense.
As you've said, the data type of u.LastLogon is DateTime?. This means that it may or may not have a value. By casting to DateTime, you are requiring it to have a value. In this case, it does not.
Depending on what you're trying to do with it, you may want to check the HasValue property:
userRow["LastLogon"] = u.LastLogin.HasValue ?
(object) u.LastLogin.ToShortDateString() : DBNull.Value;
If your database LastLogon column is of DateTime type, then you should be able to do:
userRow["LastLogon"] = u.LastLogin.HasValue ?
(object) u.LastLogin.Value : DBNull.Value;
You need to do something like the following in your data access code:
DataTable dt = ExecuteSomeQuery() ;
object value = dt.Rows[0]["nullable_datetime_column"] ;
DateTime? instance = value != null && value is DateTime ? (DateTime?)value : (DateTime?)null ) ;
If the column returned is NULL, it will be returned as a System.DBNull, otherwise it will be returned as an instance of DateTime (or whatever the appropriate mapped type is — int, string, etc). Consequently, you need to check the type of object returned from the query before trying to cast it.
Looks like you are trying to call a method (dcdt.ToShortDateString()) on a DateTime? which doesn't have a value (it is, indeed, null). Try this:
dcdt.HasValue ? dcdt.ToShortDateString() : String.Empty;
EDIT (Just re-read the question): Also, don't try to convert to DateTime. Preserve the nullable.
EDIT #2 (based on comments):
Try this:
if (dcdt.HasValue)
{ userRow["DateCreated"] = dcdt.ToShortDateString(); }
else
{ userRow = DbNull.Value }
I saw that Dexter asked how he should go about it. Well, I would create an extension.
static class DateTimeExtensions
{
public static string ToString(this DateTime? dateTime, string format)
{
return dateTime.HasValue ? dateTime.Value.ToString(format) : String.Empty;
}
}
And then you can do:
DateTime? dt = null;
DateTime? dt2 = DateTime.Now;
Console.WriteLine(dt.ToString("dd-MM-yy"));
Console.WriteLine(dt2.ToString("dd-MM-yy"));
Note that I can call extension method on a nullable type if the object is null.
The problem is .NET null is not the same as SQL NULL. SQL Null is System.DBNull. So it is a [non-null] value in .NET.
Short answer
DateTime? dateTime = u.LastLogon?.ToShortDateString()
Related
if (File.Exists(settingsFile))
{
string[] lines = File.ReadAllLines(settingsFile);
if (lines.Length > 0)
{
trackBarHours.Value = Convert.ToInt32(optionsfile.GetKey("trackbarhours"));
trackBarMinutes.Value = Convert.ToInt32(optionsfile.GetKey("trackbarminutes"));
trackBarSeconds.Value = Convert.ToInt32(optionsfile.GetKey("trackbarseconds"));
savedMilliseconds = Convert.ToInt32(optionsfile.GetKey("milliseconds"));
dateTimePicker1.Value = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue"));
richTextBox1.Text = optionsfile.GetKey("result");
}
}
because the key "timetargetvalue" is not yet created in the settingsFile because i didn't saved it yet for the first time the value of the key of "timetargetvalue" is '01/01/0001 00:00:00'
in that case that there is no yet the key hwo can i handle the datetime exception ?
dateTimePicker1 is a DateTimePicker control.
the exception is on the line :
dateTimePicker1.Value = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue"));
System.ArgumentOutOfRangeException: 'Value of '01/01/0001 00:00:00' is not valid for 'Value'. 'Value' should be between 'MinDate' and 'MaxDate'.
Parameter name: Value'
what should i check against of so it will not throw the exception ?
DateTimePicker.Value must be above DateTimePicker.MinimumDateTime, which is 'January 1, 1753'.
When you haven't set the timetargetvalue, it will resolve to '01/01/0001 00:00:00', as you have seen, which is too early.
So you need to check the value before assigning it to DateTimePicker.Value.
You can do it like this:
DateTime tempDateTime = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue");
dateTimePicker1.Value = tempDateTime >= DateTimePicker.MinimumDateTime ? tempDateTime : DateTimePicker.MinimumDateTime;
When dealing with a Struct such as DateTime that does not have any value we need to consider that this is not a class and can not be set to null. It must always have some value. (see https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=net-7.0)
The exception mentions in a round about way that the range of acceptable values is between dateTimePicker1.MinDate and dateTimePicker1.MaxDate so one option is to check if your value is within this range. But it's unlikely to be the best option. (see https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datetimepicker.mindate?view=windowsdesktop-6.0)
I'm pretty sure that DateTime default value is equal to that of DateTime.Min but if you really wanted to check if the value is default then I would suggest comparing it to default(DateTime) would be better.
This pretty much covers the use of DateTime and value defaults when null is not an option. Which brings up a possibly more desirable option. Encapsulation.
We could instead encapsulate the DateTime struct into a Nullable class. The encapsulating class will be nullable and will also be able to present the encapsulated value through a property called Value. (see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types)
There are two ways to declare such a Nullable class, both of which compile to the same thing:
Nullable<DateTime> myNullableDate = null;
DateTime? anotherNullableDate = null;
Since the DateTime is encapsulated in a Nullable object we can start using a null reference check. We can also call a method on Nullable called HasValue which returns a bool (True if it has a value).
EDIT: I notice that you're not doing any checks before trying to parse the DateTime and then directly setting it into the DateTimePicker.Value which can accept a null value. (although setting null won't clear a previously set value).
As such perhaps what you might want to do is handle the scenario a bit better and then use a DateTime.TryParse() instead. (see https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tryparse?view=net-7.0)
e.g. (not the most optimized code, but I think it's easier to follow along in a more verbose form)
private DateTime? LoadDateFromOptions(string key)
{
var rawValue = optionsfile.GetKey(key);
if (!string.IsNullOrEmpty(rawValue))
{
return null;
}
DateTime dateValue;
bool isSuccess = DateTime.TryParse(rawValue, out dateValue);
if (isSuccess)
{
return dateValue;
}
else
{
return null;
}
}
and then instead of having that exception you can load the value optionally a bit more like this:
var timeTarget = LoadDateFromOptions("timetargetvalue");
if (timeTarget != null)
{
dateTimePicker1.Value = timeTarget;
}
I am trying to determine the difference between a DateTime and a DateTime? using reflection. Please see my test code below:
public class TestClass
{
public DateTime testDate1 { get; set; }
public DateTime? testDate2 { get; set; }
}
public void Test()
{
TestClass testing = new TestClass();
var props = typeof(TestClass).GetProperties();
foreach (PropertyInfo p in props)
{
object o = p.GetValue(testing);
if (typeof(DateTime?).IsInstanceOfType(o))
{
o = DateTime.Now;
}
if (typeof(DateTime).IsInstanceOfType(o))
{
if (((DateTime)o) == DateTime.MinValue)
{
o = null;
}
}
Console.WriteLine(string.Format("{0} = {1}", p.Name, (o ?? "NULL").ToString()));
}
}
The output of this code is the opposite to what i would expect. Currently the output is:
testDate1 = 26/01/2016 16:15:00
testDate2 = NULL
I am expecting testDate1 to be null and testDate2 to contain the value.
When debugging this code, it seems that the first pass using testDate1 passes both of the typeof if statements, the second fails both of the if statements. Can anybody help me understand and hopefully try and catch the specific nullable instance of the date time?
To note i have also tried switching to a definition and test on Nullable just in case, but it made no difference.
Many thanks!
First, keep in mind that testDate1 can never be null because DateTime is a struct. If you declare a DateTime without intitializing it, it will get the default value of DateTime.MinValue. testDate2, on the other hand, is a Nullable struct, where the default value is null(-ish... it's actually a value that represents null, but not null itself).
IsInstanceOfType is using o's GetType() method in the background to verify that its type is the same as the type you are comparing to (in this case, DateTime?). However, if you take a look at the documentation, it states:
Calling GetType on a Nullable type causes a boxing operation to be performed when the type is implicitly converted to Object. Therefore GetType always returns a Type object that represents the underlying type, not the Nullable type.
So, if you step through the foreach loop for the testDate1 property, you'll see that the first condition will return true (since testDate1 can't be null, which means it has to be of type DateTime). You then step into the second if-condition (though that's effectively just doing the same check again), but you don't enter the inner if because o currently has a value of DateTime.Now.
Now stepping through for testDate2 (which is holds a null value), you will see that you don't enter either of the if-conditionals because null doesn't have a type. As such, your object will remain null throughout the second iteration of the loop, giving you the output you see there.
NOTE: Just so you know, the way you're "assigning" values to o doesn't modify the original TestClass at all. Consider the following:
TestClass testing = new TestClass();
var prop = typeof(TestClass).GetProperty("testDate1");
// Here we get the current value of testing.testDate1, which is the default DateTime.MinValue
object o = prop.GetValue(testing);
// Here we set o to null... has ZERO effect on testing.testDate1.
o = null;
// What you actually want is probably the following.
// (Remember though that testDate1 can't be null... this just sets it back to DateTime.MinValue.)
prop.SetValue(testing, null);
The answer is you can't.
If you have an object date there is no way to know if it orginally comes from a nullabe DateTime or not.
DateTime? nullable = DateTime.Now;
object o = nullable;
The assignment to o is morally equivalent to
object temp = null;
if (nullable.HasValue)
{
temp = nullable.Value;
}
o = temp;
As you can see, the information of the nullable type is lost and what you are really getting is the boxed nullable's value.
This is easy to see by simply doing o.GetType() which will return DateTime if the nullable had a value or you will get a NullReferenceException if it didn't.
This does not mean that you can not determine if the declared type of a property, method or member is nullable or not. You can do this easily enough via reflection.
Thank you for so much useful comments and links. I realise that it was the property i should have been inspecting and not the object. I am using this:
Nullable.GetUnderlyingType(p.PropertyType)
It allows me to determine what i am dealing with and is pretty effective. I still end up switching on typeof(T).Name but i will cross that bridge when i come to it :)
I have to live with the fact that functional code vs ugly code remains an internal battle!
Getting an error that has me stumped. I'm assuming it's something simple but can't seem to figure this one out, this is the code that is causing the error:
if ((string) _nullableDateTimePicker1.Value != string.Empty && _nullableDateTimePicker1.Value != null) {
_nullableDateTimePicker1.Value = null;
}
When clicking on the search button in my windows form, this is what I get popping up:
Unable to cast object of type 'System.DateTime' to type 'System.String'.
It appears the type of the nullable-type instance of _nullableDateTimePicker1 is DateTime, which is not a string; you would need to compare with a DateTime or convert that to a string.
So, in the simplest sense:
_nullableDateTimePicker1.Value.ToString() != string.Empty
However, beware the danger of not checking HasValue, as this would cause a NullReferenceException if Value is null; So, your check is a little backwards.
And even then, if it wasn't null, you'd have a DateTime.MinValue, and so ToString wouldn't return an empty string. Therefore, check for null on the nullable thing, and if not null, compare to DateTime.MinValue (unless there's a quirk specifically in your code which means it could have a different 'default'.
if ((string) _nullableDateTimePicker1.Value .....
Probably, _nullableDateTimePicker1.Value returns a DateTime. As the message explains, you can't directly cast a DateTime to a string.
In this part (string) _nullableDateTimePicker1.Value != string.Empty you are trying to cast value to string. But Value is DateTime. The second part of this if is enough.
(string) _nullableDateTimePicker1.Value
throws the exception when _nullableDateTimePicker1 is null.
Don't use (string) when trying to check if value is not null
This code should work:
if (_nullableDateTimePicker1.Value != null && Convert.ToString(_nullableDateTimePicker1.Value) != string.Empty) {
_nullableDateTimePicker1.Value = null;
}
It looks like your _nullableDateTimePicker1 object is a Nullable<DateTime> (DateTime?), in which case you're getting this error because you can't cast it to a string.
(string) _nullableDateTimePicker1.Value
It looks like you're just trying to ensure that it has a valid DateTime, in which case you only need to do the null check. Without knowing exactly what you're trying to do that's my advice.
DateTimePicker.Value returns DateTime type you cannot cast it string, what you need is to conver to string.
string dateTime = _nullableDateTimePicker1.Value.ToString();
so your code will be:
string dateTime = _nullableDateTimePicker1.Value.ToString();
if (!string.IsNullOrEmpty(dateTime))
{
dateTime = null;
}
I am not sure about setting the DateTimePicker value to null.
I have DAL where I convert database null value to their equivalent representation in C#. For example:
NULL for Numeric = 0
NULL for String = String.Empty
NULL for DateTime = "1/1/0001" (i.e. DateTime.MinValue)
The problem, for date, lies in the presentation layer, especially in GridViews. You cannot show 1/1/01 to users.
What I used to do is check if myDate.Year=1 or myDate.Year < AcceptedDate and display empty string, but seems to be extra effort unlike other types
Please am open to better approach. Thanks.
Use Nullable datatype to store null value.
DateTime? value = null;
int? myNullableInt = 1;
value = DateTime.Now;
How to check whether variable has value or null
if (value!=null)
String value can store null, so there is no diffrent datatype for string to store null.
string var;
if (var == null)
or
if (String.IsNullOrEmpty(var))
You can also use DateTime.MinValue constant.
http://msdn.microsoft.com/en-us/library/system.datetime.minvalue.aspx
Your conditions would be:
if (myDate == DateTime.MinValue)
You can use Nullable DateTime, so you will return DateTime? instead of DateTime from your DAL. This way you can check if returned value is null.
DateTime? dateTime = null;
As the others mention, you could use a System::Nullable<DateTime>.
The other approach I've seen is to use a standard DateTime and just use a special value such as DateTime.MinValue. This is useful if you need to honor an existing interface's types and can't change the DateTime to a Nullable<DateTime>.
You can either use a Nullable DateTime as the others suggested, or use this trick:
(To prevent non valid defaults.)
// If dateTime has not been initialize, initialize to Now
// (or to any other legal inital values)
dateTime = ((dateTime != new DateTime()) ? dateTime : DateTime.Now);
This trick is useful if you have to use a non-nullable DateTime and want to provide a default if none. (E.g. you have a non-nullable DateTime column in a DB and want to set the value only if row is new.)
I don't think you have much choice but to make the check like you have been and display accordingly. A nullable type might make things easier for you. Depending on your data, even the numeric should be treated this way. DBNull != 0.
Q:
I want to check the DateTime against null value to empty the cell in my report if the datetime is null.but i don't know how to do this :it appears like this 1/1/0001 if it was null.and i want it to be empty cell.
This is the datatype in my dataset :
and this is the expression value of my column :
=FormatDateTime(Fields!D_DateTime.Value,2)
As I told you in my comment, you should check if your date is DateTime.MinValue (the minimum value a date can assume, which is exactly 01/01/0001).
if (your_date_property == DateTime.MinValue)
{
// Do what you need
}
=IIf(FormatDateTime(Fields!D_DateTime.Value,2)=CDate("1/1/0001"),"",FormatDateTime(Fields!D_DateTime.Value,2))
Thanks a lot ,i think this fixes my problem.
As datetime is a struct rather than class i.e. a value type rather than a reference type; it must be initialized with some value. It cannot have null values.
Hence to check the default value you should check the equality with DateTime.MinValue
i.e.
if(D_DateTime.Value == DateTime.MinValue)
{
//write code here for default value handling
}
Change the type of the field in the dataset (rd:TypeName) to System.Nullable (Of System.DateTime). Then you can simply test =Fields!D_DateTime.Value Is Nothing.
Like #Marco suggested you can check for MinValue. And if you want to pass NULL to the nullable parameter, you can use the following code for reportviewer parameter.
Vb.Net
Dim rpFrom As New ReportParameter("FromDate", New String() {Nothing}, False)
C#
ReportParameter rpFrom = new ReportParameter("FromDate", new string[] { null }, false);