确保DateTime属性返回DateTimeKind.Utc

San*_*ken 4 linq-to-entities entity-framework .net-4.0

是否可以在Kind == DateTimeKind.Utc 使用.edmx文件或t4模板的实体对象中定义DateTime属性?

如果可能,使用t4,请描述如何更改属性.目前该属性生成为:

[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.DateTime Created
{
    get
    {
        return _created;
    }
    internal set
    {
        OnCreatedChanging(value);
        ReportPropertyChanging("Created");
        _created = StructuralObject.SetValidValue(value);
        ReportPropertyChanged("Created");
        OnCreatedChanged();
    }
}
private global::System.DateTime _created;
partial void OnCreatedChanging(global::System.DateTime value);
partial void OnCreatedChanged();
Run Code Online (Sandbox Code Playgroud)

Jan*_*ris 12

我确保所有DateTime值都被重新作为Utc DateTimes的解决方案如下:

我使用了与迈克尔相同的方法(参见其他博客文章:https://stackoverflow.com/a/9386364/1069313)然后我更深入地潜水,并使用反射来搜索DateTime和DateTime?

首先,我在我的DbContext Extensions方法类中编写了三个方法.因为我需要将它用于多个DbContexts

public static void ReadAllDateTimeValuesAsUtc(this DbContext context)
{
        ((IObjectContextAdapter)context).ObjectContext.ObjectMaterialized += ReadAllDateTimeValuesAsUtc;
}

private static void ReadAllDateTimeValuesAsUtc(object sender, ObjectMaterializedEventArgs e)
{
    //Extract all DateTime properties of the object type
    var properties = e.Entity.GetType().GetProperties()
        .Where(property => property.PropertyType == typeof (DateTime) ||
                           property.PropertyType == typeof (DateTime?)).ToList();
    //Set all DaetTimeKinds to Utc
    properties.ForEach(property => SpecifyUtcKind(property, e.Entity));
}

private static void SpecifyUtcKind(PropertyInfo property, object value)
{
    //Get the datetime value
    var datetime = property.GetValue(value, null);

    //set DateTimeKind to Utc
    if (property.PropertyType == typeof(DateTime))
    {
        datetime = DateTime.SpecifyKind((DateTime) datetime, DateTimeKind.Utc);
    }
    else if(property.PropertyType == typeof(DateTime?))
    {
        var nullable = (DateTime?) datetime;
        if(!nullable.HasValue) return;
        datetime = (DateTime?)DateTime.SpecifyKind(nullable.Value, DateTimeKind.Utc);
    }
    else
    {
        return;
    }

    //And set the Utc DateTime value
    property.SetValue(value, datetime, null);
}
Run Code Online (Sandbox Code Playgroud)

然后我转到我的WebsiteReadModelContext的构造函数,它是一个DbContext对象并调用ReadAllDateTimeValuesAsUtc方法

public WebsiteReadModelContext()
{
      this.ReadAllDateTimeValuesAsUtc();
}
Run Code Online (Sandbox Code Playgroud)


aar*_*man 8

对于我们的情况,总是如前所述指定DateTimeKind是不切实际的:

DateTime utcDateTime = DateTime.SpecifyKind(databaseDateTime, DateTimeKind.Utc);
Run Code Online (Sandbox Code Playgroud)

如果要强制将来自数据库的所有DateTime对象指定为UTC,则需要添加T4转换文件并为所有DateTime和可为空的DateTime对象添加其他逻辑,以便将它们初始化为DateTimeKind.Utc

我有一篇博文,一步一步解释:http://www.aaroncoleman.net/post/2011/06/16/Forcing-Entity-Framework-to-mark-DateTime-fields-at-UTC.aspx

简而言之:

1)为.edmx模型创建.tt文件

2)打开.tt文件并找到"WritePrimitiveTypeProperty"方法.

3)替换现有的setter代码.这是ReportPropertyChangingReportPropertyChanged方法回调之间的所有内容,具有以下内容:

<#+ if( ((PrimitiveType)primitiveProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.DateTime)
            {
#>
        if(<#=code.FieldName(primitiveProperty)#> == new DateTime())
        {
            <#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+ 
            if(ef.IsNullable(primitiveProperty))
            {  
#>              
            if(value != null)
                <#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>.Value, DateTimeKind.Utc);
<#+             } 
            else
            {#>
            <#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>, DateTimeKind.Utc);                
<#+ 
            } 
#>
        }
        else
        {
            <#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
        }
<#+ 
        }
        else
        {
#>
    <#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+ 
        }
#>
Run Code Online (Sandbox Code Playgroud)

  • 试着关注你的博客并发帖.使用EF5和100%新的T4.看不到相同的设置.此外,已经生成了2个TT文件,Entity.tt和Entity.Context.tt.这仍然是最新的还是我需要找到不同的解决方案? (2认同)