At work we came across an interesting issue while storing all dates in Microsoft SQL Server database in UTC time. We're going to allow users from different time zones to use the app and the UTC time will need to be translated to their time zone off of UTC. However, this week we were scratching our heads trying to figure out how to get Entity Framework 4 to default our database results as UTC. We are using MVC and doing Ajax data calls to a view which resturns data as javascript, and under the covers uses the Javascript serializer. Not knowing that the date is already in UTC time, the serializer attempts to convert it to UTC based on the timezone the system is in (Pacific Standard Time in our case). The issue is resolved if you do the following to any DateTime object before you pass it off for serialization:

CreatedDate = DateTime.SpecifyKind(CreatedDate, DateTimeKind.Utc);

At issue is that by default, Entity Framework is setting the DateTimeKind property to "Unspecified", and Javascript Serializer (as well as I think things like RIA services) decides that it probably isn't in UTC. The issue has been discussed before: http://www.west-wind.com/weblog/posts/471402.aspx

It was impractical for my team to remember to set this property every single time for all of our database dates, there could be hundreds. Instead, we'd like to force Entity Framework to initialize dates with DateTimeKind.Utc set. Entity Framework uses an .edmx file to generate a code file (something.designer.cs). Inside that file you'll see that DateTime fields are created as so:

 

        /// 
        /// No Metadata Documentation available.
        /// 
        [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
        [DataMemberAttribute()]
        public global::System.DateTime CreatedDate
        {
            get
            {
                return _CreatedDate;
            }
            set
            {
                OnCreatedDateChanging(value);
                ReportPropertyChanging("CreatedDate");
    		    _CreatedDate = StructuralObject.SetValidValue(value);
    		    ReportPropertyChanged("CreatedDate");
                OnCreatedDateChanged();
            }
        }
        private global::System.DateTime _CreatedDate;
        partial void OnCreatedDateChanging(global::System.DateTime value);
        partial void OnCreatedDateChanged();

What we'd like to do is add the following lines of code to each DateTime property class:

if(_CreatedDate == new DateTime())
{
     _CreatedDate = StructuralObject.SetValidValue(value);
     _CreatedDate = DateTime.SpecifyKind(_CreatedDate, DateTimeKind.Utc);               
}
else
{
    _CreatedDate = StructuralObject.SetValidValue(value);
}

OR a very similar addition for nullable DateTime objects that checks for null and passes the value if it exists:

 

if(_DeletedDate == new DateTime())
{
    _DeletedDate = StructuralObject.SetValidValue(value);
    				
    if(value != null)
    	_DeletedDate = DateTime.SpecifyKind(_DeletedDate.Value, DateTimeKind.Utc);
}
else
{
    _DeletedDate = StructuralObject.SetValidValue(value);
}

Since these classes get auto-generated every time there is a change in your .edmx class, the best way I've found to do this is to use a T4 template (.tt) transform to add this functionality. Here are the steps you'll need to take to put this in to practice:

1) If you don't already have it, from Visual Studio go to "Tools" -> "Extension Manager" and download "tangible T4 Editor". After you've installed, restart Visual Studio to get snytax highlighting.

2) Go to your .edmx file and right-click on any empty space and select "Add Code Generation Item..."

3) In the "Add New Item" dialog, select "ADO.NET Entity Object Generator"

4) Open the new .TT file is and search for the "WritePrimitiveTypeProperty" method is. This is where the magic is going to happen. We're going to add additional rules so that all DateTime and nullable DateTime objects get initialized specified as UTC.

 

5) Find the line: ReportPropertyChanging("<#=primitiveProperty.Name#>"); *for me this was line 599

Replace what is currently between the "ReportPropertyChanging" and the "ReportPropertyChanged" method callbacks the following. This adds the additional UTC DateTimeKind setting step if the property is a DateTime:

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

 

That's it! In total, the following is my entire "WritePrimitiveTypeProperty":

////////
//////// Write PrimitiveType Properties.
////////
private void WritePrimitiveTypeProperty(EdmProperty primitiveProperty, CodeGenerationTools code)
{
MetadataTools ef =
new MetadataTools(this);
#>

/// <summary>
/// <#=SummaryComment(primitiveProperty)#>
/// </summary><#=LongDescriptionCommentElement(primitiveProperty, 1)#>
[EdmScalarPropertyAttribute(EntityKeyProperty=<#=code.CreateLiteral(ef.IsKey(primitiveProperty))#>, IsNullable=<#=code.CreateLiteral(ef.IsNullable(primitiveProperty))#>)]
[DataMemberAttribute()]
<#=code.SpaceAfter(NewModifier(primitiveProperty))#><#=Accessibility.ForProperty(primitiveProperty)#> <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.Escape(primitiveProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(primitiveProperty))#>get
{
<#+ if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
{
#>
return StructuralObject.GetValidValue(<#=code.FieldName(primitiveProperty)#>);
<#+
}
else
{
#>
return <#=code.FieldName(primitiveProperty)#>;
<#+
}
#>
}
<#=code.SpaceAfter(Accessibility.ForSetter((primitiveProperty)))#>set
{
<#+
if (ef.IsKey(primitiveProperty))
{
if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
{
#>
if (!StructuralObject.BinaryEquals(<#=code.FieldName(primitiveProperty)#>, value))
<#+
}
else
{
#>
if (<#=code.FieldName(primitiveProperty)#> != value)
<#+
}
#>
{
<#+
PushIndent(CodeRegion.GetIndent(
1));
}
#>
<#=ChangingMethodName(primitiveProperty)#>(value);
ReportPropertyChanging(
"<#=primitiveProperty.Name#>");

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

ReportPropertyChanged(
"<#=primitiveProperty.Name#>");
<#=ChangedMethodName(primitiveProperty)#>();
<#+
if (ef.IsKey(primitiveProperty))
{
PopIndent();
#>
}
<#+
}
#>
}
}
private <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.FieldName(primitiveProperty)#><#=code.StringBefore(" = ", code.CreateLiteral(primitiveProperty.DefaultValue))#>;
partial void <#=ChangingMethodName(primitiveProperty)#>(<#=code.Escape(primitiveProperty.TypeUsage)#> value);
partial void <#=ChangedMethodName(primitiveProperty)#>();
<#+
}