0

Along the lines of these questions:

  1. 'datetime2' error when using entity framework in VS 2010 .net 4.0
  2. How to fix the datetime2 out-of-range conversion error using DbContext and SetInitializer?

I am attempting to use code first to generate a database based on models that I do not own. I.E. I can not modify the models. (I am bringing a desktop application up to speed with a server application.)

I understand that the DateTime value in C# has an invalid MinDate when converting to SqlDateTime. Furthermore, the SQL Express instance created from Entity Framework does not support datetime2. I've tried to apply a filter with default values using a convention:

this.Properties<DateTime>()
                .Configure(o => o.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).HasColumnAnnotation("SqlDefaultValue", "GETDATE()"));

However, when I do this, I get the error Cannot insert the value NULL into column 'CreatedDate', table 'blahblahblah.Companies'; column does not allow nulls. INSERT fails.

I'm not sure I understand that error message as the values are never null. But I'm guessing because the DatabaseGeneratedOption is computed, the value isn't being set.

So far, none of these options has worked for the date time. If there is a way to prefilter inserts and updates, I could run a check on the datetime values and set their values to the SqlDateTime min value. However, my Google foo isn't returning any results for that type of operation. If there is no way to do this, I may just make a helper function that uses reflection to auto adjust all datetime objects appropriately.

Community
  • 1
  • 1
teynon
  • 7,540
  • 10
  • 63
  • 106

1 Answers1

0

I ended up writing a helper function to pre-update datetime values.

public static class DateTimeSwitch
{
    public static void DateTimeToSqlDateTime(this object obj)
    {
        Type objType = obj.GetType();

        if (typeof(IEnumerable).IsAssignableFrom(objType))
        {
            IEnumerable enumerable = (IEnumerable)obj;
            if (enumerable != null)
            {
                foreach (object c in enumerable)
                {
                    if (c != null)
                        c.DateTimeToSqlDateTime();
                }
            }
        }
        else
        {
            PropertyInfo[] properties = objType.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                if (typeof(DateTime).IsAssignableFrom(property.PropertyType))
                {
                    // Get the value, adjust it.
                    DateTime value = (DateTime)property.GetValue(obj, null);
                    if (value < (DateTime)SqlDateTime.MinValue)
                    {
                        property.SetValue(obj, (DateTime)SqlDateTime.MinValue, null);
                    }
                }
                else if (!property.PropertyType.IsPrimitive && typeof(String) != property.PropertyType && typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
                {
                    IEnumerable enumerable = (IEnumerable)property.GetValue(obj, null);
                    if (enumerable != null)
                    {
                        foreach (object c in enumerable)
                        {
                            if (c != null)
                                c.DateTimeToSqlDateTime();
                        }
                    }
                }
                else if (!property.PropertyType.IsPrimitive)
                {
                    if (property.PropertyType.Assembly == objType.Assembly)
                    {
                        var value = property.GetValue(obj, null);
                        if (value != null) value.DateTimeToSqlDateTime();
                    }
                }
            }
        }
    }
}
teynon
  • 7,540
  • 10
  • 63
  • 106