Setting a dateTime property to null - c#

I have this class which is a nuget package with a nullable dateTime property. This property is set depending on when another property is filled. Now, I do not want this property to have this property and I will like to set it null. Here is the class in the private nuget package
public class myClass
{
private string _todaysDate;
public DateTime? todaysDateAsDateTime
{
get
{
DateTime? result;
return !this.todaysDate.TryParseToDate(out result) ? new DateTime?() : result;
}
set => this.todaysDate = value.ParseToDate();
}
public string todaysDate
{
get => this._todaysDate;
set => this._todaysDate= value;
}
}
ParseToDate and TryParseToDate are extension menthods in thesame nuget
public static string ParseToDate(this DateTime? value) => value?.ToString("yyyy-MM-dd", (IFormatProvider) CultureInfo.InvariantCulture);
public static bool TryParseToDate(this string value, out DateTime? result)
{
if (string.IsNullOrEmpty(value))
{
result = new DateTime?();
return true;
}
bool flag = false;
DateTime result1 = DateTime.UtcNow;
if (value.Length == 10)
flag = DateTime.TryParseExact(value, "yyyy-MM-dd", (IFormatProvider) CultureInfo.InvariantCulture, DateTimeStyles.None, out result1);
if (flag)
{
result = new DateTime?(DateTime.SpecifyKind(result1, DateTimeKind.Utc));
return true;
}
result = new DateTime?();
return false;
}
when using this class, is there a possibility of setting todaysDateAsDateTime to null? because I do not want to have this value. The todaysDate is filled by the program when I use it in my application

In the property todaysDateAsDateTime, you need manage case in get/set when the value is null :
public class myClass
{
private string _todaysDate;
public DateTime? todaysDateAsDateTime
{
get =>
this._todaysDate != null && this._todaysDate.TryParseToDate(out DateTime? result) ?
result : null;
set => this._todaysDate = value?.ParseToDate();
}
public string todaysDate
{
get => this._todaysDate;
set => this._todaysDate = value;
}
}
I think you begin with C#, I add the same code without sugar syntax :
public class myClass
{
private string _todaysDate;
public DateTime? todaysDateAsDateTime
{
get
{
DateTime? result;
if(this._todaysDate!=null && this.todaysDate.TryParseToDate(out result))
{
return result;
}
else
{
null;
}
}
set
{
if(value != null)
{
this._todaysDate = value.ParseToDate();
}
else
{
this._todaysDate = null;
}
}
}
public string todaysDate
{
get => this._todaysDate;
set => this._todaysDate = value;
}
}

Related

"Data is Null. This method or property cannot be called on Null values." on DateTime [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
c# why cant a nullable int be assigned null as a value
Im trying to convert my reader[3] object which is datetime to be null if there is no lastPostDate for a Forum but it says Im missing a conversion.
Error:
Type of conditional expression cannot be determined because there is no implicit conversion between <null> and 'System.DateTime'
public class Forums
{
public List<Forum> GetForums()
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMS"].ConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("sproc_Forums_GetForums", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default);
List<Forum> forums = new List<Forum>();
while (reader.Read())
{
var title = reader[6].ToString();
var threadCount = (int)reader[5];
var lastPostTitle = reader[4].ToString();
// below is where im having a problem
Nullable<DateTime> lastPostDate = (reader[3] == DBNull.Value ? null : Convert.ToDateTime(reader[3]));
var lastPostBy = reader[2].ToString();
var forumGroup = reader[1].ToString();
var description = reader[0].ToString();
Forum forum = new Forum(0, "",DateTime.Now,
reader["Title"].ToString(),description,
0,false,"","",DateTime.Now,true,
forumGroup, (int)threadCount, lastPostBy,
lastPostDate, lastPostTitle);
forums.Add(forum);/**/
}
return forums;
}
}
}
Below is my class object for Forum with a Nullable lastPostDate
public class Forum
{
public Forum(int forumID, string addedBy, DateTime addedDate, string title, string description, int parentID, bool moderated,
string imageUrl, string updatedBy, DateTime? updatedDate, bool active, string forumGroup, int threadCount, string lastPostBy,
Nullable<DateTime> lastPostDate, string lastPostTitle)
{
this.ForumID = forumID;
this.AddedBy = addedBy;
this.AddedDate = addedDate;
this.Title = title;
this.Description = description;
this.ParentID = parentID;
this.Moderated = moderated;
this.ImageUrl = imageUrl;
this.UpdatedBy = updatedBy;
this.UpdatedDate = updatedDate;
this.Active = active;
this.ForumGroup = forumGroup;
this.ThreadCount = threadCount;
this.LastPostBy = lastPostBy;
this.LastPostDate = lastPostDate;
this.LastPostTitle = lastPostTitle;
}
private int _forumID;
public int ForumID
{
get { return _forumID; }
set { _forumID = value; }
}
private string _addedBy;
public string AddedBy
{
get { return _addedBy; }
set { _addedBy = value; }
}
private DateTime _addedDate = DateTime.Now;
public DateTime AddedDate
{
get { return _addedDate; }
set { _addedDate = value; }
}
private string _title = "";
public string Title
{
get { return _title; }
set { _title = value; }
}
private string _description = "";
public string Description
{
get { return _description; }
set { _description = value; }
}
private int _parentID = 0;
public int ParentID
{
get { return _parentID; }
set { _parentID = value; }
}
private bool _moderated = false;
public bool Moderated
{
get { return _moderated; }
set { _moderated = value; }
}
private string _imageUrl = "";
public string ImageUrl
{
get { return _imageUrl; }
set { _imageUrl = value; }
}
private string _updatedBy = "";
public string UpdatedBy
{
get { return _updatedBy; }
set { _updatedBy = value; }
}
private DateTime? _updatedDate = null;
public DateTime? UpdatedDate
{
get { return _updatedDate; }
set { _updatedDate = value; }
}
private bool _active = false;
public bool Active
{
get { return _active; }
set { _active = value; }
}
private string _forumGroup = "";
public string ForumGroup
{
get { return _forumGroup; }
set { _forumGroup = value; }
}
private int _threadCount = 0;
public int ThreadCount
{
get { return _threadCount; }
set { _threadCount = value; }
}
private string _lastPostBy = "";
public string LastPostBy
{
get { return _lastPostBy; }
set { _lastPostBy = value; }
}
private Nullable<DateTime> _lastPosteDate = null;
public Nullable<DateTime> LastPostDate
{
get { return _lastPosteDate; }
set { _lastPosteDate = value; }
}
private string _lastPostTitle = "";
public string LastPostTitle
{
get { return _lastPostTitle; }
set { _lastPostTitle = value; }
}
}
You might want to do it like this:
DateTime? lastPostDate = (DateTime?)(reader.IsDbNull(3) ? null : reader[3]);
The problem you are having is that the ternary operator wants a viable cast between the left and right sides. And null can't be cast to DateTime.
Note the above works because both sides of the ternary are object's. The object is explicitly cast to DateTime? which works: as long as reader[3] is in fact a date.
Make sure those two types are nullable DateTime
var lastPostDate = reader[3] == DBNull.Value ?
null :
(DateTime?) Convert.ToDateTime(reader[3]);
Usage of DateTime? instead of Nullable<DateTime> is a time saver...
Use better indent of the ? expression like I did.
I have found this excellent explanations in Eric Lippert blog:
The specification for the ?: operator states the following:
The second and third operands of the ?: operator control the type of
the conditional expression. Let X and Y be the types of the second and
third operands. Then,
If X and Y are the same type, then this is the type of the conditional
expression.
Otherwise, if an implicit conversion exists from X to Y,
but not from Y to X, then Y is the type of the conditional expression.
Otherwise, if an implicit conversion exists from Y to X, but not from
X to Y, then X is the type of the conditional expression.
Otherwise,
no expression type can be determined, and a compile-time error occurs.
The compiler doesn't check what is the type that can "hold" those two types.
In this case:
null and DateTime aren't the same type.
null doesn't have an implicit conversion to DateTime
DateTime doesn't have an implicit conversion to null
So we end up with a compile-time error.
Cast the null literal: (DateTime?)null or (Nullable<DateTime>)null.
You can also use default(DateTime?) or default(Nullable<DateTime>)
And, as other answers have noted, you can also apply the cast to the DateTime value rather than to the null literal.
EDIT (adapted from my comment to Prutswonder's answer):
The point is that the conditional operator does not consider the type of its assignment target, so it will only compile if there is an implicit conversion from the type of its second operand to the type of its third operand, or from the type of its third operand to the type of its second operand.
For example, this won't compile:
bool b = GetSomeBooleanValue();
object o = b ? "Forty-two" : 42;
Casting either the second or third operand to object, however, fixes the problem, because there is an implicit conversion from int to object and also from string to object:
object o = b ? "Forty-two" : (object)42;
or
object o = b ? (object)"Forty-two" : 42;
You can try this
var lastPostDate = reader[3] == DBNull.Value ?
default(DateTime?):
Convert.ToDateTime(reader[3]);

Validation inside a class property

The code is as follows:
public class MyEvent
{
public string EventTitle { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool IsInsideSameMonth
{
get
{
// No code is bug-free, so we assume this situation may occur somehow.
if (StartDate > EndDate)
{
// And when this occurs, we want to halt the application by throwing exception to prevent further potential damage.
throw new MyEventException("Start date is not supposed to be greater than end date.");
}
return (StartDate.Year == EndDate.Year && StartDate.Month == EndDate.Month);
}
}
public void Validate()
{
if (StartDate > EndDate)
{
throw new MyEventException("Start date is not supposed to be greater than end date.");
}
if (String.IsNullOrWhiteSpace(EventTitle))
{
throw new MyEventException("Title cannot be empty.");
}
}
}
public class MyEventException : Exception
{
public MyEventException(string message)
: base(message)
{
}
}
It might seem redundant that I perform StartDate > EndDate validation inside the IsInsideSameMonth property. I just prefer being on the safe side. But it feels as if I am doing something wrong but I cannot describe it.
Is this a good practice? Please share your valuable experience and thoughts.
You shouldn't use Auto-implemented property. You should instead use a backing private field and then check while setting the property like:
private DateTime _StartDate;
public DateTime StartDate
{
get { return _StartDate; }
set
{
if (value > _EndDate)
{
throw new MyEventException("Start date is not supposed to be greater than end date.");
}
else
{
_StartDate = value;
}
}
}
private DateTime _EndDate;
public DateTime EndDate
{
get { return _EndDate; }
set { _EndDate = value; }
}
Your current code would allow the user to set StartDate to any value and you will only realize if you check your property IsInsideSameMonth.
For the EventTitle you could declare a backing field and make the validation inside the setter of the property. Something like this:
string eventTitle;
public string EventTitle
{
get
{
return eventTitle;
}
set
{
if(!IsNullOrWhiteSpace(value))
eventTitle = value;
else
throw new MyEventException("Title cannot be empty.");
}
}
As for the DateTime objects you could follow the same path:
private DateTime startDate;
public DateTime StartDate
{
get
{
return startDate;
}
set
{
if (value > EndDate)
{
throw new MyEventException("Start date is not supposed to be greater than end date.");
}
else
{
startDate = value;
}
}
}
private DateTime endDate;
public DateTime EndDate
{
get
{
return endDate;
}
set
{
endDate = value;
}
}
It's better to control values when the properties are set, so you need to convert your automatic properties to old style (properties with private field) and put your checking there.
Here is the Microsoft property design guide.
Here is an example checking the values when setting, throwing if invalid. I've also defined functions for validation to reduce redundant code (in case you want to change your validation or error messaging- it will be in one location).
public class MyEvent
{
public bool IsInsideSameMonth
{
get
{
return (StartDate.Year == EndDate.Year && StartDate.Month == EndDate.Month);
}
}
private string _EventTile;
public string EventTitle
{
get { return _EventTile; }
set
{
ValidateTitle(value); // this will throw if invalid and leave the value of _EventTitle unchanged
_EventTile = value;
}
}
private DateTime _StartDate = DateTime.MinValue;;
public DateTime StartDate
{
get { return _StartDate; }
set
{
ValidateDates(value, EndDate); // this will throw if invalid and leave the value of _StartDate unchanged
_StartDate = value;
}
}
private DateTime _EndDate = DateTime.MaxValue;;
public DateTime EndDate
{
get { return _EndDate; }
set
{
ValidateDates(StartDate, value); // this will throw if invalid and leave the value of _EndDate unchanged
_EndDate = value;
}
}
private void ValidateDates(DateTime start, DateTime end)
{
if (start > end)
{
throw new MyEventException("Start date is not supposed to be greater than end date.");
}
}
private void ValidateTitle(string title)
{
if (String.IsNullOrWhiteSpace(title))
{
throw new MyEventException("Title cannot be empty.");
}
}
public void Validate()
{
ValidateDates(StartDate, EndDate);
ValidateTitle(EventTitle);
}
}
public class MyEventException : Exception
{
public MyEventException(string message)
: base(message)
{
}
}

Can I use LINQ To Search an inner list in a List of Lists?

I have these classes:
public class ZoneMember
// a zone member is a member of a zone
// zonemembers have ports, WWPNs, aliases or all 3
{
private string _Alias = string.Empty;
public string MemberAlias {get{return _Alias;} set{_Alias = value; } }
private FCPort _Port = null;
public FCPort MemberPort { get { return _Port; } set { _Port = value; } }
private string _WWPN = string.Empty;
public string MemberWWPN { get { return _WWPN; } set { _WWPN = value; } }
private bool _IsLoggedIn;
public bool IsLoggedIn { get { return _IsLoggedIn; } set { _IsLoggedIn = value; } }
private string _FCID;
public string FCID {get{return _FCID;} set{ _FCID=value; } }
}
public class Zone
{
public List<ZoneMember> MembersList = new List<ZoneMember>();
private string _ZoneName;
public string zoneName{ get{return _ZoneName;} set{_ZoneName=value;} }
public Zone(string n) { zoneName=n; }
}
public class ZoneSet
{
private string _ZoneSetName;
private int _VSANNum;
public string ZoneSetName{get{ return _ZoneSetName;} set{_ZoneSetName=value;} }
public int VSANNum{ get{ return _VSANNum;} set{_VSANNum=value;} }
public bool isActive;
public List<Zone> ZoneList = new List<Zone>();
}
I want to find all the zones in a Zoneset that have a zone member with a specific value for a property in the MembersList.
I know something like this will work - in this case I am searching on the WWPN property:
// assumes myZoneSet has already been instantiated ad has zones in it
// and inputWWPN in the select statement has the value we want
List<Zone> myZoneList = new List<Zone>();
foreach (Zone z in myZoneset)
{
var zm=null;
zm = from member in z.MembersList where member.MemberWWPN == inputWWPN select member;
// if we find a matching member, add this zone to the list
if (zm != null)
{ myZoneList.Add(z);
}
}
Is there a way to use LINQ to do the entire thing? I am not sure what the terminology would be in database terms.
This small query should be all you need:
var myZoneList = myZoneSet.ZoneList
.Where(z => z.Any(member => member.MemberWWPN == inputWWPN))
.ToList();
Try this -
List<Zone> listOfZone = zoneSet.ZoneList.Where(e => e.Any(p => p.MemberWWPN == inputWWPN)).ToList();
myZoneList =myZoneSet.SelectMany(z => z.MembersList).Where(m => m.MemberWWPN == "somestring").ToList();
I hope this will help.

Return a null from Function which returns a DateTime

public static DateTime ResolveDate()
{
return null;
}
Im required to return a null value from a function which returns a DateTime Type .. My Main Objective is to NOT to use MinValue or return a new Datetime(); [Which Returns a Default Date] and Frontend display the Date as a Empty Value (Blank) -> ""
public static DateTime? ResolveDate()
{
if ( someconditon = true )
{
return DateTime.Now
}
else
{
return null;
}
}
An alternative is to use something like TryParse is working
Public static bool TryResolve (out Resolvedate)
{
if ( someconditon = true )
{
Resolvedate = DateTime.Now
return true;
}
else
{
return false;
}
}
Make it nullable
public static DateTime? ResolveDate()
{
return null;
}
You can then return null as you want and check accordingly
Have a read of this Nullable Types for more information.
You can either return a Nullable<DateTime> like so:
public static DateTime? ResolveDate()
{
if (notResolvable)
{
return null;
}
}
Which would be useable like so:
var date = ResolveDate();
if (date.HasValue)
{
// Use date.Value here
}
Or use the Try naming convention like so:
public static bool TryResolveDate(out DateTime date)
{
date = default(DateTime);
if (notResolvable)
{
return false;
}
}
Which would be useable like so:
DateTime date;
if (TryResolveDate(out date))
{
// Use date here
}
bool somecondition = true;
public DateTime? ResolveDate()
{
DateTime? date = null;
if (somecondition == true)
{
date = DateTime.Now;
return DateTime.Now;
}
else return date;
}

NHibernate - Conversion failed when converting datetime from binary/varbinary string

Note, this is some ancient NHibernate installation! I have the following NHibernate class:
[Serializable]
[Class(Table = "SomeEvents")]
public class SomeEvent
{
[Property(Column="processDate")]
public DateTime? ProcessDate { get; set; }
}
When trying to update some events like:
using (ISession session = FDK_Hibernate_Manager.OpenSession())
{
IQuery query = session.CreateQuery(string.Format("FROM {0} e WHERE e.ContractId = :cid", typeof(ContractLeverconditiesEvent)));
query.SetInt32("cid", contractId);
foreach(var evnt in query.List().Cast<SomeEvent>())
{
evnt.ProcessDate = DateTime.Now;
session.SaveOrUpdate(evnt);
}
session.Flush();
}
I receive the following exception:
Conversion failed when converting datetime from binary/varbinary string.
So I basically guess that NHibernate doesn't understand my DateTime? yet. My NHibernate install doesn't have any fancy Nullables.NHibernate.NullableDateTimeType. So anyone has a clue to solve this ancient NHibernate issue?
I ended up with this (although it can require some work in error-checking and such :-))
Implement it using [Property(Column = "processDate", TypeType = typeof(NullableDateTime))]
class NullableDateTime : IUserType
{
#region IUserType Members
public new bool Equals(object obj, object obj2)
{
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public object DeepCopy(object value)
{
return value;
}
public bool IsMutable
{
get { return true; }
}
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
object o = rs[names[0]];
if (o == DBNull.Value) return new Nullable<DateTime>();
else
return new Nullable<DateTime>(((System.Data.SqlTypes.SqlDateTime)o).Value);
}
public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
{
System.Data.Common.DbParameter parameter = (System.Data.Common.DbParameter)cmd.Parameters[index];
if (value == null)
{
parameter.Value = DBNull.Value;
return;
}
else
{
parameter.Value = new System.Data.SqlTypes.SqlDateTime((DateTime)value);
}
}
public Type ReturnedType
{
get { return this.GetType(); }
}
public NHibernate.SqlTypes.SqlType[] SqlTypes
{
get { return new NHibernate.SqlTypes.SqlType[] { new SqlDateTimeType() }; }
}
#endregion
}
public class SqlDateTimeType : NHibernate.SqlTypes.SqlType
{
public SqlDateTimeType() : base(System.Data.DbType.DateTime)
{
}
}
Unfortunately, you'll probably have to use a proxy value (magic number) for the null date. 1/1/1900 is a common choice. If you can map a private member (I don't use attributes), you could control the value through the public property:
public class SomeEvent
{
private DateTime _processDate; // map this
public SomeEvent()
{
_processDate = new DateTime(1900, 1, 1);
}
public DateTime? ProcessDate
{
get
{
if (_processDate == new DateTime(1900, 1, 1))
{
return null;
}
return _processDate;
}
set
{
_processDate = value ?? new DateTime(1900, 1, 1);
}
}
}

Categories

Resources