Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 确保DateTime属性返回DateTimeKind.Utc_Entity Framework_Linq To Entities_.net 4.0 - Fatal编程技术网

Entity framework 确保DateTime属性返回DateTimeKind.Utc

Entity framework 确保DateTime属性返回DateTimeKind.Utc,entity-framework,linq-to-entities,.net-4.0,Entity Framework,Linq To Entities,.net 4.0,是否可以使用.edmx文件或t4模板在Kind==DateTimeKind.Utc的实体对象中定义日期时间属性 如果可能使用t4,请描述如何更改属性。当前,属性生成为: [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)] [DataMemberAttribute()] public global::System.DateTime Created { get { return

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

如果可能使用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();

是的,可以使用自定义T4模板

您只需调整属性设置器和获取器

尝试POCO方法可能更容易

对于EF1:


对于EF4:

对于我们的案例,始终指定DateTimeKind是不切实际的,如前所述:

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

我有一篇博客文章一步一步地解释了这一点:

简言之:

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

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

3) 替换现有的setter代码。这是
ReportPropertyChanging
ReportPropertyChanged
方法回调之间的所有内容,包括以下内容:

<#+ 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)#>);
<#+ 
        }
#>

如果(=新日期时间())
{
=StructuralObject.SetValidValue(值);
if(值!=null)
=DateTime.SpecifyKind(.Value,DateTimeKind.Utc);
=DateTime.SpecifyKind(,DateTimeKind.Utc);
}
其他的
{
=StructuralObject.SetValidValue(值);
}
=StructuralObject.SetValidValue(值);

确保所有日期时间值都读取为Utc日期时间的我的解决方案如下:

我使用了与Michael相同的方法(见其他博客帖子:),只是后来我深入了一点,并使用反射搜索DateTime和DateTime

首先,我在DbContext扩展方法类中编写了三个方法。因为我需要在多个DBContext中使用它

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);
}
然后我转到我的WebsiteReadModelContext的构造函数,它是一个DbContext对象,并调用ReadAllDateTimeValuesAsUtc方法

public WebsiteReadModelContext()
{
      this.ReadAllDateTimeValuesAsUtc();
}

以什么方式调整属性设置器/获取器?尝试关注您的博客和帖子。使用EF5和T4的100%新版本。看不到与您相同的设置。另外,已经生成了两个TT文件,即Entity.TT和Entity.Context.TT。这仍然是最新的还是我需要找到一个不同的解决方案?这只是救了我的命。我的Web API站点(使用ServiceStack.Text)返回ISO8601格式的日期时出现问题,但末尾没有Z表示UTC。我的数据库是100%UTC,因此这意味着我需要在实体或消息契约中指定所有数据的绑定。这个补丁为我节省了几个小时的难看编码。谢谢这种方法的一个缺点是,使用
ObjectContext
属性实际上会实例化到数据库的连接。开箱即用EF6尝试等待,直到数据从数据库实际读/写到数据库。有没有办法保持这种懒惰的行为?