Make sure DateTime properties return DateTimeKind.Utc

Is it possible to define DateTime properties in object objects that have a Kind == DateTimeKind.Utc value using either a .edmx file or a t4 template?

If possible using t4, please describe how to change the property. Currently, the property is being generated as:

 [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(); 
+4
source share
3 answers

For our case, it was impractical to always specify DateTimeKind, as indicated earlier:

 DateTime utcDateTime = DateTime.SpecifyKind(databaseDateTime, DateTimeKind.Utc); 

If you want all DateTime objects leaving the database to be specified in UTC, you need to add a T4 conversion file and add additional logic for all DateTime and nullable DateTime objects so that they are initialized as DateTimeKind. Utc

I have a blog post that explains this step by step: http://www.aaroncoleman.net/post/2011/06/16/Forcing-Entity-Framework-to-mark-DateTime-fields-at-UTC. aspx

In short:

1) Create a .tt file for your .edmx model

2) Open the .tt file and find the WritePrimitiveTypeProperty method.

3) Replace the existing setup code. This is all between the ReportPropertyChanging and ReportPropertyChanged method ReportPropertyChanged with the following:

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

My solution is to ensure that all DateTime values ​​are read as Utc DateTimes:

I used the same approach as Michael (see another blog post: fooobar.com/questions/87236 / ... ), only then did I go a little deeper and use reflection to search for DateTime and DateTime?

First, I wrote three methods that are in my DbContext Extensions class of methods. Because I need to use it for multiple 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); } 

And then I go to the constructor of my SiteReadModelContext, which is a DbContext object and calls the ReadAllDateTimeValuesAsUtc method

 public WebsiteReadModelContext() { this.ReadAllDateTimeValuesAsUtc(); } 
+11
source

Yes, you could use a custom T4 template.

You just need to configure your setters and recipients.

It might be easier to try the POCO approach;

For EF1: http://code.msdn.microsoft.com/EFPocoAdapter/Release/ProjectReleases.aspx?ReleaseId=1580

For EF4: http://thedatafarm.com/blog/data-access/agile-entity-framework-4-repository-part-1-model-and-poco-classes/

0
source

All Articles