是否可以使用.edmx文件或t4模板在Kind == DateTimeKind.Utc
的实体对象中定义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();
答案 0 :(得分: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);
}
然后我转到我的WebsiteReadModelContext的构造函数,它是一个DbContext对象并调用ReadAllDateTimeValuesAsUtc方法
public WebsiteReadModelContext()
{
this.ReadAllDateTimeValuesAsUtc();
}
答案 1 :(得分:8)
对于我们的情况,总是如前所述指定DateTimeKind是不切实际的:
DateTime utcDateTime = DateTime.SpecifyKind(databaseDateTime, DateTimeKind.Utc);
如果要强制将数据库中出现的所有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代码。这是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)#>);
<#+
}
#>
答案 2 :(得分:0)
是的,可以使用自定义T4模板。
您只需要调整属性设置器和getter。
尝试POCO方法可能更容易;
对于EF1:http://code.msdn.microsoft.com/EFPocoAdapter/Release/ProjectReleases.aspx?ReleaseId=1580