2010-10-05 8 views
0

Je travaille sur une application Silverlight et j'utilise les services de données RIA et nHibernate.Problème de mise à jour d'une à plusieurs relations lors de l'utilisation de services ria avec nhibernate

Actuellement, j'ai une entité avec une relation un à plusieurs avec une autre entité.

public class Employer { 
    [Key] 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
} 

public class Person { 
    [Key] 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    [Include] 
    [Association("PersonCurrentEmployer", "CurrentEmployerId", "Id", IsForeignKey = true)] 
    public virtual Employer CurrentEmployer { get; set; } 
    public virtual int? CurrentEmployerId { get; set; } 
} 

La propriété CurrentEmployerId est définie sans insert et aucune mise à jour dans les applications. Du côté de Silverlight, j'ai mis la propriété CurrentEmployer de la personne à un employeur existant du côté client.

personEntity.CurrentEmployer = megaEmployer; 
dataContext.SubmitChanges(); 

Du côté du serveur, est réglé sur megaEmployer.IdCurrentEmployerId de l'entité personne, mais la CurrentEmployer est null. Parce que j'utilise la propriété CurrentEmployer et non le CurrentEmployerId pour enregistrer la relation, la relation n'est pas modifiée.

Y at-il un moyen de forcer RIA à envoyer l'objet CurrentEmployer avec le sauver ou dois-je utiliser le CurrentEmployerId sur le côté serveur pour charger l'employeur et le mettre à la CurrentEmployer?

+0

Oui, j'ai le même problème ici: http://stackoverflow.com/questions/4921465/wcf-ria-submitchanges-doesnt-send-master-properties-back-to-the-server-side Il semble que NHibernate n'ait toujours pas assez de support, je suppose; nous devrions opérer ForeighKey, pas les entités! http://www.scip.be/index.php?Page=ArticlesNET30&Lang=NL C'est une honte, je pense que Microsoft Team devrait nous écouter =) – EvgeniyK

Répondre

1

Y at-il un moyen de forcer RIA à envoyer l'objet CurrentEmployer avec le sauver ou dois-je utiliser le CurrentEmployerId sur le côté serveur pour charger l'employeur et le mettre à la CurrentEmployer?

Je suis également confronté à ce problème. Fondamentalement, vous devez soit utiliser l'attribut [Composition] (que je ne recommanderais pas), ou charger l'entité à partir de la base de données, côté serveur. La composition embrouille le modèle de données client et ne prend pas en compte tous les cas dont vous avez besoin. [Il y a beaucoup plus sur la composition dans les forums RIA.silverlight.net)

[MISE À JOUR] Une fois que vous implémentez le cache de second niveau, le souci de lire les entités de support de la base de données disparaît la plupart du temps, car ils seront chargés cache Aussi, si vous avez seulement besoin d'un proxy pour que NHibernate ne se plaint pas, alors regardez dans Get/Load (je ne me souviens plus lequel) .. qui retournera un proxy NH et résultera en un single-column-and-entity select de la base de données . (Si vous essayez d'accéder à une autre propriété du proxy, NH sélectionnera le reste, vous pouvez en trouver plus sur le blog d'Ayende ..) [/ UPDATE]

Le plus gros problème que j'ai est de faire NHib réellement enregistrer et charger la relation. (J'utilise aussi Fluent). La réponse des parties responsables a jusqu'à présent été "waah, vous ne pouvez pas faire cela, il semble que RIA n'a pas été développé avec NHib à l'esprit" .. qui est une réponse merde, à mon humble avis. Au lieu de m'aider à comprendre comment le mapper, ils me disent que je fais mal d'avoir un ForeignKey dans mon entité (NHib ne devrait pas se soucier que j'ai mon FK dans mon entité) ...

0

Je veux partager ce que j'ai fait pour faire ce travail, parce que le soutien 'officiel' pour ce scénario était ... disons simplement inutile au mieux, et carrément impoli au pire. Par ailleurs, vous avez eu la même idée que moi: faire que la clé étrangère ne soit pas insérée/mise à jour. MAIS, je l'ai aussi fait Generated.Always(). De cette façon, il lira toujours la valeur en arrière.

De plus, je substitue DomainService.Submit() et DomainService.ExecuteChangeSet(). Je lance une transaction NHibernate dans le Submit (bien que je ne sois pas encore sûr que cela fasse ce que je pense).Au lieu de mettre ma logique de sauvegarde dans les méthodes InsertSomeEntity() ou UpdateSomeEntity(), je le fais dans ExecuteChangeSet. c'est à cause de NHibernate, et de son BESOIN d'avoir le graphe d'entité entièrement bidirectionnel et hydraté avant d'effectuer des actions dans NHibernate. Cela inclut le chargement d'entités à partir de la base de données ou de la session lorsqu'un élément enfant rencontre le câble des services RIA. (J'ai commencé le chemin des méthodes d'écriture pour obtenir les diverses autres parties du graphique car ces méthodes spécialisées en avaient besoin, mais j'ai trouvé qu'il était plus facile de tout faire en une seule méthode. moi pour effectuer l'insertion/mises à jour contre les objets enfant d'abord, ce qui pour les nouveaux éléments est un problème.)

Je veux faire un commentaire sur l'attribut de composition. Je maintiens mon précédent commentaire sur le fait de ne pas le recommander pour les collections d'entités enfants standard, MAIS, il fonctionne très bien pour supporter les composants NHibernate, sinon RIA ne renverra jamais l'instance parent (de la composition), qui est nécessaire pour que NHibernate fonctionne droite.

Je n'ai pas fourni de code ici parce que je devrais faire quelques gros travaux, mais ce n'est pas un problème pour moi si vous voulez le voir.

1

La raison pour laquelle vous ne voyez pas votre CurrentEmployer côté client est que vous n'avez pas configuré votre association correctement.

Les services RIA ne fonctionnent pas avec les références de la manière habituelle, donc le référencement de votre employeur du côté client ne fonctionne pas. Les services RIA fonctionnent avec des ensembles d'entités et créent les "références" en fonction des attributs d'association. Votre employeur a besoin d'une propriété avec une association de retour à la personne comme suit.

public class Employer 
    { 
     private Person person; 

     [Key] 
     public virtual int Id { get; set; } 
     public virtual string Name { get; set; } 
     public virtual int PersonID { get; set; } 

     [Include] 
     [Association("PersonCurrentEmployer", "PersonID", "Id", IsForeignKey = false)] 
     public virtual Person Person { 
      get 
      { 
       return this.person; 
      } 

      set 
      { 
       this.person = value; 
       if (value != null) 
       { 
        this.PersonID = value.Id; 
       } 
      } 
     } 
    }