Stellen Sie sicher, dass DateTime-Eigenschaften DateTimeKind.Utc zurückgeben

.net-4.0 entity-framework linq-to-entities

Frage

Ist es möglich, DateTime-Eigenschaften in Entitätsobjekten zu definieren, die von Kind == DateTimeKind.Utc indem Sie entweder die EDMX-Datei oder eine T4-Vorlage verwenden?

Beschreiben Sie, wenn möglich, t4, wie Sie die Eigenschaft ändern können. Derzeit wird die Eigenschaft generiert als:

[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();

Akzeptierte Antwort

In unserem Fall war es nicht praktikabel, DateTimeKind immer wie zuvor angegeben anzugeben:

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

Wenn Sie alle aus der Datenbank kommenden DateTime-Objekte als UTC festlegen möchten, müssen Sie eine T4-Transformationsdatei hinzufügen und zusätzliche Logik für alle DateTime- und nullfähigen DateTime-Objekte hinzufügen, sodass sie als DateTimeKind.Utc initialisiert werden

Ich habe einen Blogbeitrag, der dies Schritt für Schritt erklärt: http://www.aaroncoleman.net/post/2011/06/16/Forcing-Entity-Framework-to-mark-DateTime-fields-at-UTC.aspx

Zusamenfassend:

1) Erstellen Sie die .tt-Datei für Ihr .edmx-Modell

2) Öffnen Sie die .tt-Datei und suchen Sie die Methode "WritePrimitiveTypeProperty".

3) Ersetzen Sie den vorhandenen Einstellcode. Das ist alles , was zwischen dem ReportPropertyChanging und die ReportPropertyChanged Methode Rückrufe mit den folgenden:

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

Beliebte Antwort

Meine Lösung, um sicherzustellen, dass alle DateTime-Werte als Utc DateTimes gelesen werden, lautet wie folgt:

Ich habe die gleiche Herangehensweise wie Michael verwendet (siehe anderer Blog-Beitrag: https://stackoverflow.com/a/9386364/1069313 ). Erst dann tauchte ich ein wenig tiefer und suchte nach DateTime und DateTime?

Zuerst habe ich drei Methoden geschrieben, die sich in meiner DbContext Extensions-Methodenklasse befinden. Weil ich es für mehrere DbContexts verwenden muss

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

Und dann gehe ich zum Konstruktor meines WebsiteReadModelContext-Objekts, das ein DbContext-Objekt ist, und rufe die ReadAllDateTimeValuesAsUtc-Methode auf

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


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum