EF Code First插入/更新时的预过滤日期时间

时间:2016-09-09 13:00:48

标签: c# entity-framework datetime

沿着这些问题:

  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?
  3. 我首先尝试使用代码根据我不拥有的模型生成数据库。 I.E.我无法修改模型。 (我正在通过服务器应用程序快速启动桌面应用程序。)

    我了解C#中的DateTime值在转换为SqlDateTime时具有无效的MinDate。此外,从Entity Framework创建的SQL Express实例不支持datetime2。我尝试使用约定来应用具有默认值的过滤器:

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

    但是,当我这样做时,我收到错误Cannot insert the value NULL into column 'CreatedDate', table 'blahblahblah.Companies'; column does not allow nulls. INSERT fails.

    我不确定我是否理解该错误消息,因为值永远不会为空。但我猜是因为DatabaseGeneratedOptioncomputed,因此未设置该值。

    到目前为止,这些选项都没有适用于日期时间。如果有预过滤插入和更新的方法,我可以检查日期时间值并将其值设置为SqlDateTime最小值。但是,我的Google foo并未返回该类型操作的任何结果。如果没有办法做到这一点,我可能会创建一个使用反射的辅助函数来自动调整所有日期时间对象。

1 个答案:

答案 0 :(得分:0)

我最终编写了一个辅助函数来预先更新日期时间值。

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();
                    }
                }
            }
        }
    }
}