2016-06-05 6 views
2

Ich nehme eine API, die die folgende Klasse für Zeit hat.Entity Framework Server Seite berechneter Wert

public class CRTime 
{ 
    public DateTime? datetime { get; set; } 
    public string timezone { get; set; } 
} 

Ich möchte das in ein einzelnes DateTime-Feld übersetzen.

Hier ist ein Beispiel für das vollständige Objekt, das mir zurückgegeben wird und wie ich versuche, das DateTime-Feld zu berechnen, das dann in der Datenbank gespeichert wird.

public class ReturnObject 
{ 
    [NotMapped] 
    // This comes from the api, but is not synced to database 
    public CRTime CRCreated { get; set; } 

    // this is stored in our db, should be calculated from CRCreated 
    public DateTime? CreatedDB { get 
     { 
      var val = (CRCreated != null) ? CRCreated.datetime : null; 
      return val; 
     } 
     private set { } 
    } 
    // other fields go here 
} 

Dies funktioniert perfekt auf Rekord schaffen, aber wenn ich die Platte mit dem Entity.Migration Rahmen und AddOrUpdate versuchen und aktualisieren, überschreibt das Update den Wert und setzt sie immer auf NULL.

Was ist die beste Lösung zum Erstellen einer serverseitigen berechneten Spalte, die dann mit der Datenbank synchronisiert wird.

Side Hinweis: Ich verwende NewtonSoft Json, um das Objekt in mein Entity-Framework-Objekt zu deserialisieren und dann an Entity Framework AddOrUpdate zu übergeben.

+0

Durchdenken Dinge, vielleicht gibt es ein Problem, da die CRC-Eigenschaft nicht in der Datenbank gespeichert wird, so auf Aktualisierung, Entity Framework hat Schwierigkeiten, den Vergleich und die Berechnung darauf, da es seinen Wert von der db, wo es ist null anstatt von dem Objekt von der API zu kommen? – TWilly

+0

Ich habe auch versucht, [DatabaseGenerated (DatabaseGeneratedOption.Computed)] -Attribut, aber dies ist für Berechnungen auf der db-Seite, die keine Informationen in CRCreated Objekt hat. – TWilly

Antwort

2

Dies ist wegen einer ziemlich verwirrenden Eigenart von AddOrUpdate.

AddOrUpdate bestimmt, ob eine Entität offensichtlich neu oder vorhanden ist. Dies erfolgt durch Abfragen der Datenbank nach der Entität anhand ihres Primärschlüssels oder eines Schlüssels, den Sie angeben können. Jetzt können zwei Dinge passieren:

  • Es findet nicht die Entität in der Datenbank; Ihr Entitätsobjekt ist als markiert.
  • Es findet eine Entität, aber im Gegensatz zu dem, was Sie erwarten würden, ist Ihr Entitätsobjekt immer noch Detached! Die gefundene Entität bleibt verborgen und das ist das Objekt EF Updates am Ende. Er kopiert die Werte von Ihrer eigenen Entität in diese, wodurch die verborgene Entität als Modified markiert werden kann.

Offensichtlich durch diesen leeren Setter wird CreatedDB immer null sein, wenn es aus der Datenbank geholt ist. Für EF ist CRCreated nicht vorhanden. Es liest wahrscheinlich einen CreatedDB Wert von Ihrem Objekt, aber wieder verhindert der leere Setter, dass es in das versteckte Objekt kopiert wird und es wird als null aktualisiert.

Sie müssen entscheiden, wie Sie das beheben. Wahrscheinlich ist der beste Weg, den Setter tatsächlich dazu zu bringen, die CRCreated Instanz zu modifizieren (oder zu erstellen).

Alternativ können Sie auf AddOrUpdate verzichten und versuchen, das vorhandene Objekt selbst zu finden. Wenn du es findest, ist es nicht mehr versteckt, also kannst du damit machen, was du willst.

1

Ich würde erwarten, dass es NULL sein wird, nachdem Sie es vom Db gelesen haben. Die private set; ist natürlich komisch und blockiert die einwandfreie Funktion von EF.

Sie Ihre selbst einen großen Gefallen tun könnte, wenn Sie in der Lage sind Datetime zu verwenden, aber in der aktuellen Situation:

Ihre Eigenschaft logisch 'berechnet werden könnte, sondern auf die Datenbank sollte es als normales behandelt und umgesetzt werden Lese-/Schreibeigenschaft.