C#


With my need to exchange data between a ASP.NET and PHP web applications, I decided to use JSON. The .NET team did a good job by integrating JSON de/serialization into the language (NET 3.5) but they decided not to follow JSON specifications for some good reasons. Serializing an object that has a DateTime property will insert a string that won’t be understood by json_decode of PHP.

On the site of JSON, there is no such thing as a date type.  I have taken the ISO 8601 path which is my preferred date format (MySQL and Swedish Locale standard)

Consider the following class:

[code lang="C#"]
[DataContract]
public class Person
{
[DataMember]
public DateTime DateOfBirth { set; get; }
[DataMember]
public string Names { set; get; }
}
[/code]

By Serializing it you will get something like

[code]

{"DateOfBirth" : "\/Date(1210408872000+0200)\/", "Names" : "Kavuna ka Lyaziga"}

[/code]

That Date is not defined as a JSON type. In case your JSON will be used directly by JavaScript or .NET (C#, VB) you will not need to write extra codes.

In some installations of the MySQL server, some invalid dates are legal.

At the URL http://dev.mysql.com/doc/refman/4.1/en/date-and-time-types.html I can read:
MySQL version through 4.1 accept certain “illegal” values for dates, such as '1999-11-31'. This is useful when you want to store a possibly incorrect value specified by a user (for example, in a web form) in the database for future processing. MySQL verifies only that the month is in the range from 0 to 12 and that the day is in the range from 0 to 31. These ranges are defined to include zero because MySQL allows you to store dates where the day or month and day are zero in a DATE or DATETIME column. This is extremely useful for applications that need to store a birthdate for which you do not know the exact date. In this case, you simply store the date as '1999-00-00' or '1999-01-00'. If you store dates such as these, you should not expect to get correct results for functions such as DATE_SUB() or DATE_ADD that require complete dates.

MySQL also allows you to store '0000-00-00' as a “dummy date.” This is in some cases more convenient, and uses less data and index space, than storing NULL values.

This behaviour causes problems when using the MySQL Connector/NET. First, Visual Studio 2005 DateTime structure does not accept such invalid date values. It only accepts values between “0001-01-01 00:00:00″ through “9999-12-31 23:59:59.99999″ and these values should be real dates (Check remarks at system.datetime ).

To deal with this problem, connector/NET has MySqlDateTime type that can contain such invalid dates. This class has a property, IsValidDateTime, that is set to true when the date is valid and false otherwise. Currently, the way this property is calculated does not guarantee that the value contained in a MySqlDateTime object can be easily converted into a legal DateTime object. Currently, this property will return FALSE if and only if the object contains a ZERO date (or ZERO dateTime: 0000-00-00).

To overcome this, the property checking should also check if this date is legal in .NET
I have created a sample function that can replace the one in Connector/Net 1.0.7 and I named it IsStrictlyValidDateTime.

Its definition looks like:

[code lang="C#"]
///
/// Indicates if this object contains a value that can be represented as a DateTime
///
public bool IsStrictlyValidDateTime
{
get
{
// In case this represents a zero date, return FALSE
if (year == 0 || month == 0 || day == 0)
{
return false;
}

// Check http://msdn2.microsoft.com/en-us/library/xcfzdy4x(d=ide).aspx
// Here I try assign the value of this object to a DateTime object.
// In case the date is illegal, an Exception will be thrown
// In case the date is legal, the value will be accepted
try
{
DateTime dt = new DateTime(year, month, day);
return true;
} catch (ArgumentOutOfRangeException)
{
//year is less than 1 or greater than 9999.
//-or-
//month is less than 1 or greater than 12.
//-or-
//day is less than 1 or greater than the number of days in month
return false;
} catch (ArgumentException)
{
// The specified parameters evaluate to less than MinValue or more than MaxValue
return false;
}
}
}
[/code]

And the changed file can be seen at /Types/MySqlDateTime.cs

I still don’t understand why a date like “0000-10-01″ was made invalid in .NET (ten months after date ZERO).

In MySql connector .NET, the MySqlDateTime class has no public constructor (it does have constructors but defined as internal). This makes it impossible to use that type in applications.

The bug at MySQL Bug #15112 is caused by the absent public contructor. To try and solve this problem, I added a public contructor in the file mysql-connector-net-1.0.7\mysqlclient\Types\MySqlDateTime.cs
[code lang="C#"]public MySqlDateTime()
{
// Set the value to the lowest value that a DateTime value can have
year = 1;
month = 1;
day = 1;
}
public MySqlDateTime(DateTime val)
{
year = val.Year;
month = val.Month;
day = val.Day;
hour = val.Hour;
minute = val.Minute;
second = val.Second;
}[/code]

This makes it possible to instantiate a MySqlDateTime and set it values.
One can do like :
[code lang="C#"] MySql.Data.Types.MySqlDateTime myDate = new MySql.Data.Types.MySqlDateTime();
System.Console.WriteLine(myDate.ToString()); // 0001-01-01 00:00:00

// or

MySql.Data.Types.MySqlDateTime myDate2 = new MySql.Data.Types.MySqlDateTime(new DateTime(2006,08,05,23,20,15));
System.Console.WriteLine(myDate2.ToString()); // 2006-08-05 23:20:15[/code]

The modified file can be accessed at /Types/MySqlDateTime.cs
For those who won’t re-build the connector themselves I have also uploaded a binary at /bin/net-2.0/Release/MySql.Data.dll

There is still a problem concerning the values saved into this type: for example an object of this type can report that it contains a valid date when it contains “2006-02-31 00:00:00″. This is wrong because February cannot have 31 days. So, the checking of validity of this class needs a change. Currently, the only invalid date is “0000-00-00″ (MySQL ZERO date).

While using Connector/.NET to connect to MySQL I prefer accessing the DataReader fields using their names.

Like

[code lang="C#"]
string sCustomerName = dbReader.GetString("CustomerName") ;
int nSomeIntegerVariable = dbReader.GetInt32("AnIntegerField"); [/code]

I love doing it this way because I can reorder my columns without having to change the access code.

With the current connector, one should retreive the field Index (using the GetOrdinal() Method) and pass that ordinal (Index) to one of the accessors to get the value of the column.
I have been doing that but I found it cumbersome and decided to add some methods in the DataReader Class definition.

The methods I added are:
[code lang="C#"]
public bool GetBoolean(String name)
public byte GetByte(String name)
public long GetBytes(String name, long dataIndex, byte[] buffer, int bufferIndex, int length)
public char GetChar(String name)
public long GetChars(String name, long fieldOffset, char[] buffer, int bufferoffset, int length)
public String GetDataTypeName(String name)
public MySqlDateTime GetMySqlDateTime(String name)
public DateTime GetDateTime(String name)
public Decimal GetDecimal(String name)
public double GetDouble(String name)
public Type GetFieldType(String name)
public float GetFloat(String name)
public Guid GetGuid(String name)
public Int16 GetInt16(String name)
public Int32 GetInt32(String name)
public Int64 GetInt64(String name)
public String GetString(String name)
public TimeSpan GetTimeSpan(String name)
public object GetValue(String name)
public UInt16 GetUInt16(String name)
public UInt32 GetUInt32(String name)
public UInt64 GetUInt64(String name)
public bool IsDBNull(String name)[/code]

In the XML comments of each of these methods I added a line saying that
ordinal based lookups are faster.

The modified file can be accessed at
/dev/mysql/net/mysqlclient/datareader.cs
For those who won’t re-build the connector themselves I have also uploadead
a binary at
/dev/mysql/net/bin/net-2.0/Release/MySql.Data.dll