J'expérimente BreezeJS avec l'API Web en utilisant l'attribut BreezeControllerAttribute. Comment les propriétés calculées d'une entité doivent-elles être exposées ? Le seul moyen que j'ai trouvé pour le faire de manière fiable est de créer un DTO intermédiaire qui hérite de l'entité ou d'utiliser une projection. Normalement, je devrais utiliser une propriété en lecture seule pour ce scénario, mais ces propriétés semblent être ignorées.
Réponse
Trop de publicités?Lorsque Breeze fait correspondre les données de propriété JSON aux entités, il ignore les propriétés qu'il ne reconnaît pas . C'est pourquoi les données des propriétés calculées de votre classe serveur sont ignorées même si vous les voyez dans le JSON sur le fil.
Heureusement, vous pouvez apprendre à Breeze à reconnaître la propriété en en l'enregistrant comme une propriété non cartographiée . Je vais vous montrer comment. Laissez-moi d'abord vous expliquer le contexte.
Contexte
Votre propriété calculée serait "connue" du client Breeze s'il s'agissait d'une propriété calculée par la base de données. Les propriétés (régulières et calculées) adossées à la base de données sont reprises dans les métadonnées en tant que propriétés mappées.
Mais dans votre cas (si je comprends bien), la propriété est définie dans la logique de la classe côté serveur, et non dans la base de données. Elle ne figure donc pas parmi les propriétés mappées dans les métadonnées. Elle est cachée des métadonnées. Il s'agit d'une propriété d'instance non mappée.
Je suppose que vous ne le cachez pas au sérialiseur. Si vous regardez le trafic réseau pour une requête de la classe, vous pouvez voir vos données de propriété calculées arriver sur le client. Le problème est que Breeze les ignore lorsqu'il "matérialise" les entités à partir des résultats de ces requêtes.
Solution avec exemple
La solution consiste à enregistrer la propriété calculée dans le MetadataStore .
J'ai modifié le site entityExtensionTests.js de l'échantillon DocCode pour inclure ce scénario ; vous pouvez obtenir ce code sur GitHub ou attendre la prochaine version de Breeze.
Ou bien suivez simplement le code ci-dessous, en commençant par cet extrait de la page d'accueil. Employee
classe dans NorthwindModel.cs :
// Unmapped, server-side calculated property
\[NotMapped\] // Hidden from Entity Framework; still serialized to the client
public string FullName {
get { return LastName +
(String.IsNullOrWhiteSpace(FirstName)? "" : (", " + FirstName)); }
}
Et voici le test automatisé dans entityExtensionTests.js
test("unmapped property can be set by a calculated property of the server class", 2,
function () {
var store = cloneModuleMetadataStore(); // clones the Northwind MetadataStore
// custom Employee constructor
var employeeCtor = function () {
//'Fullname' is a server-side calculated property of the Employee class
// This unmapped property will be empty for new entities
// but will be set for existing entities during query materialization
this.FullName = "";
};
// register the custom constructor
store.registerEntityTypeCtor("Employee", employeeCtor);
var fullProp = store.getEntityType('Employee').getProperty('FullName');
ok(fullProp && fullProp.isUnmapped,
"'FullName' should be an unmapped property after registration");
var em = newEm(store); // helper creates a manager using this MetadataStore
var query = EntityQuery.from('Employees').using(em);
stop(); // going async
query.execute().then(success).fail(handleFail).fin(start);
function success(data) {
var first = data.results\[0\];
var full = first.FullName();
// passing test confirms that the FulllName property has a value
ok(full, "queried 'Employee' should have a fullname ('Last, First'); it is "+full);
}
});
Ce que vous devez faire se trouve dans cette petite partie de l'exemple de test :
var yourTypeCtor = function () {
this.calculatedProperty = ""; // "" or instance of whatever type is is supposed to be
};
// register your custom constructor
store.registerEntityTypeCtor("YourType", yourTypeCtor);