2016-03-31 7 views
2

Ich habe eine partielle Klassendatei erstellt, um meinem Entity-Framework generierten Modell neue Eigenschaften hinzuzufügen.OData enthalten "Benutzerdefinierte Eigenschaften", die zu Entity Framework-Modellen über Teilklassen hinzugefügt wurden

Ich verwende WebAPI + OData und die $ metadata listet meine neuen/benutzerdefinierten Eigenschaften nicht auf, und so enthält der JSON, den es zurückgibt, meine neuen/benutzerdefinierten Eigenschaften nicht.

Zum Beispiel, sagen wir mal meine Entity ist "Person"

"Person" hat eine Datenbank-Eigenschaft; NumSpouses; ein int, die in $ Metadaten wie folgt zurückgegeben: <Property Name="NumSpouses" Type="Edm.Int32"/>

Das ist großartig, aber ich hinzugefügt bekommen eine Eigenschaft wie diese in einer separaten Datei, with a partial class:

public partial class Person { 
    ... 
    public string MarriedStatus { 
    get { return this.NumSpouses==0 ? "Single" : "Married"; } 
    } 
    ... 
} 

Wie kann ich diese Immobilie in meiner OData Antworten?

<Property Name="MarriedStatus" Type="Edm.String"/>

Derzeit wenn ich für MarriedStatus in $expand gefragt (als ob es ein Navigation war .... das ist es nicht [Ich dachte, ich würde versuchen, $ sowieso zu erweitern, als ob es auf magische Weise benutzerdefinierte Eigenschaften zur Verfügung gestellt]), würde ich eine Nachricht wie diese:

{ 
    "odata.error":{ 
    "code":"","message":{ 
     "lang":"en-US","value":"The query specified in the URI is not valid. Could not find a property named 'MarriedStatus' on type 'fakeDataModels.Person'." 
},"innererror":{ 
    "message":"Could not find a property named 'MarriedStatus' on type 'fakeDataModels.Person'.","type":"Microsoft.Data.OData.ODataException","stacktrace":" at ..." 
    } 
    } 
} 
+0

Ist Ihre Teilklasse im selben Namespace wie das EF-generierte Modell? – lencharest

+0

Ja ist es. Der Namespace ist in beiden Dateien konsistent, nennen wir ihn "PersonDataModels", und beide Dateien befinden sich im selben Projekt. Ich weiß, 'Controller.Json' JSON-Serialisierung ist nicht dasselbe wie OData-Serialisierung, aber ich werde darauf hinweisen, dass JSON die 'MarriedStatus'-Eigenschaft serialisiert, es sei denn, ich sage ausdrücklich nicht zu (' ScriptIgnoreAttribute'). Vielleicht erfordert dies das Äquivalent eines "ViewModel", ich sollte meinen clientseitigen (Javascript) Code hinzufügen, der mir nur die Komfortfunktion 'getMarriedStatus()' zur Verfügung stellt. –

+0

Partielle Klassen funktionieren wie erwartet in einem Spielzeugprojekt, das ich erstellt habe. Vielleicht liegt das Problem in Ihrer OData-Konfiguration. Verwenden Sie 'ODataConventionModelBuilder' und registrieren Sie Entitätssätze einfach? Oder etwas anspruchsvoller? – lencharest

Antwort

3

MarriedStatus ist eine kalkulierte/Nur-Lese-Eigenschaft. Die ASP.NET-Implementierung von OData unterstützt derzeit keine solchen Eigenschaften. Um dieses Problem zu umgehen, fügen Sie einen Setter hinzu, der NotImplementedException auslöst.

public string MarriedStatus { 
     get { return this.NumSpouses > 0 ? "Married" : "Single"; } 
     set { throw new NotImplementedException(); } 
    } 

Optional, wenn Sie OData V4 verwenden, können Sie MarriedStatus mit Anmerkungen versehen, um anzugeben, dass es berechnet wird. Siehe Yi Ding's answer bis OData read-only property. Aber die Anmerkung ist nur beratend; Es verhindert nicht, dass Clients versuchen, eine berechnete Eigenschaft festzulegen (z. B. in einer POST-Anforderung).

+1

Es gibt jedoch immer noch ein Problem beim Versuch, die Eigenschaft als LINQ zu Entities-Drosseln zu serialisieren, wenn ein Setter vorhanden ist und die Eigenschaft nicht in der Datenbank vorhanden ist. Siehe [diese Frage] (https://stackoverflow.com/questions/6919709/only-initializers-entity-members-and-entity-navigation-properties-are-supporte) – MylesRip

0

Zusätzlich zu der Antwort von lenkarest. Sie sollten die Ignore() - Funktion der fließenden Entity Framework-API anstelle des [NotMapped] -Attributs verwenden. Weil OData nach diesem Attribut sucht, um Eigenschaften für die Serialisierung zu ignorieren. Wenn Sie die fließende API verwenden, haben Sie dieses Problem nicht.

dbModelBuilder.Entity<TEntity>() 
    .Ignore(i => i.ComputedProperty); 
+0

Aber ich möchte * mehr * Spalten enthalten .. Ich möchte Spalten nicht ignorieren. Ich sehe nicht, wie Ignore/NotMapped relevant ist. –

+0

Beachten Sie, dass .Ignore() Entity Framework einfach anweist, diese Eigenschaft zu ignorieren, als ob sie nicht in der Datenbank wäre. So wird es für Inserts, Selects, Updates ignoriert, während Sie es immer noch auf Ihrem Modell haben können. Auf diese Weise können Sie hinzufügen, was Sie wollen. Ich habe auch @MylesRip eine Antwort gegeben. – bdebaere

Verwandte Themen