2009-10-26 2 views
3

Nous avons actuellement une application qui récupère des données du serveur via un service Web et remplit un DataSet. Ensuite, les utilisateurs de l'API le manipulent à travers les objets qui à leur tour changent l'ensemble de données. Les modifications sont ensuite sérialisées, compressées et renvoyées au serveur pour être mises à jour.Enregistrer les données via un service Web à l'aide de NHibernate?

Cependant, j'ai commencé à utiliser NHibernate dans les projets et j'aime vraiment la nature déconnectée des objets POCO. Le problème que nous avons maintenant est que nos objets sont tellement liés au DataSet interne qu'ils ne peuvent pas être utilisés dans de nombreuses situations et que nous finissons par faire des objets POCO en double pour passer d'un endroit à l'autre.

Batch.GetBatch() -> calls to web server and populates an internal dataset 
Batch.SaveBatch() -> send changes to web server from dataset 

Y at-il un moyen d'atteindre un modèle similaire que nous utilisons tous les accès qui se produit de base de données via un service Web, mais utiliser NHibernate?

Modifier 1

avoir une solution partielle qui fonctionne et persistant grâce à un service Web, mais il a deux problèmes.

  1. je dois sérialisation et envoyer toute ma collection et non pas seulement changé les articles
  2. Si je tente de repeupler la collection lors du retour de mes objets alors les références que j'avais sont perdus.

Voici mon exemple de solution.

côté client

public IList<Job> GetAll() 
{ 
    return coreWebService 
     .GetJobs() 
     .BinaryDeserialize<IList<Job>>(); 
} 

public IList<Job> Save(IList<Job> Jobs) 
{ 
    return coreWebService 
      .Save(Jobs.BinarySerialize()) 
      .BinaryDeserialize<IList<Job>>(); 
} 

côté serveur

[WebMethod] 
public byte[] GetJobs() 
{ 
    using (ISession session = NHibernateHelper.OpenSession()) 
    { 
     return (from j in session.Linq<Job>() 
       select j).ToList().BinarySerialize(); 
    } 
} 

[WebMethod] 
public byte[] Save(byte[] JobBytes) 
{ 
    var Jobs = JobBytes.BinaryDeserialize<IList<Job>>(); 

    using (ISession session = NHibernateHelper.OpenSession()) 
    using (ITransaction transaction = session.BeginTransaction()) 
    { 
     foreach (var job in Jobs) 
     { 
      session.SaveOrUpdate(job); 
     } 
     transaction.Commit(); 
    } 

    return Jobs.BinarySerialize(); 
} 

Comme vous pouvez le voir, je vous envoie toute la collection au serveur chaque fois, puis retourner la collection. Mais je reçois une collection remplacée au lieu d'une collection fusionnée/mise à jour. Sans parler du fait qu'il semble très inefficace d'envoyer toutes les données d'avant en arrière quand seulement une partie de celui-ci pourrait être changé.

Edit 2

J'ai vu plusieurs références sur le web pour presque un mécanisme transparent persistant. Je ne sais pas exactement si cela fonctionnera et la plupart d'entre eux semblent très expérimentaux.

Je vais avoir du mal à trouver un remplacement fo r le modèle DataSet que nous utilisons aujourd'hui. La raison pour laquelle je veux m'éloigner de ce modèle est qu'il faut beaucoup de travail pour lier chaque propriété de chaque classe à une rangée/cellule d'un ensemble de données.Ensuite, il couple également étroitement tous mes cours ensemble.

+0

Quelle version de .net sont votre client et le serveur? Est-ce que vous allez avoir besoin de communiquer avec un client .net (ou avec quel couplage voulez-vous être?) –

+0

Version 3.5 et nous n'avons pas besoin d'interagir avec autre chose que .NET. Il peut être complètement lié à .NET en ce qui me concerne. Nous construisons le client et le serveur. –

Répondre

0

Je n'ai pris un coup d'oeil rapide à votre question, alors pardonnez-moi si ma réponse est myope, mais ici va:

Je ne pense pas que vous pouvez logiquement sortir de faire une cartographie de l'objet de domaine DTO. En utilisant les objets de domaine sur le fil, vous associez étroitement votre client et votre service, une partie de la raison d'avoir un service en premier lieu est de promouvoir un couplage lâche. C'est donc un problème immédiat. En plus de cela, vous allez vous retrouver avec une interface de logique de domaine fragile où vous ne pouvez pas apporter de modifications du côté service sans casser votre client.

Je suppose que votre meilleur pari serait de mettre en œuvre un service faiblement couplé qui implémente un REST/ou une autre interface faiblement couplée. Vous pouvez utiliser un produit tel que automapper pour simplifier et simplifier les conversions et également aplatir les structures de données si nécessaire. À ce stade, je ne connais aucun moyen de vraiment réduire la verbosité impliquée dans les couches d'interface, mais ayant travaillé sur de grands projets qui n'ont pas fait l'effort, je peux honnêtement vous dire que les économies n'étaient pas ça vaut le coup.

0

Je pense que votre question tourne autour de cette question:

http://thatextramile.be/blog/2010/05/why-you-shouldnt-expose-your-entities-through-your-services/

Êtes-vous ou n'êtes-vous pas allez envoyer ORM-entités sur le fil?

Puisque vous avez une architecture orientée services .. Je (comme l'auteur) ne recommande pas cette pratique.

J'utilise NHibernate. J'appelle ces entités ORM. Ils sont le modèle POCO. Mais ils ont des propriétés "virtuelles" qui permettent un chargement paresseux.

Cependant, j'ai aussi quelques objets DTO. Ce sont aussi des POCO. Ceux-ci n'ont pas de propriétés conviviales paresseuses.

Donc je fais beaucoup de "conversion". J'hydrate les ORM-Entities (avec NHibernate) ... et puis je finis par les convertir en Domain-DTO-Objects. Oui, ça pue au début.

Le serveur envoie les objets Domain-DTO. Il n'y a pas de chargement paresseux. Je dois les peupler avec le modèle «juste correct» de «Goldie Locks». Aka, si j'ai besoin de Parent (s) avec un niveau d'enfants, je dois le savoir d'avance et envoyer les Domain-DTO-Objects de cette façon, avec juste la bonne quantité d'hydratation. Quand j'envoie des objets Domain-DTO (du client au serveur), je dois inverser le processus. Je convertis les objets Domain-DTO en entités ORM. Et permettre à NHibernate de travailler avec les entités ORM. Comme l'architecture est "déconnectée", je fais beaucoup d'appels (NHiberntae) ".Merge()".

 // ormItem is any NHibernate poco 
     using (ISession session = ISessionCreator.OpenSession()) 
     { 
      using (ITransaction transaction = session.BeginTransaction()) 
      { 
       session.BeginTransaction(); 
       ParkingAreaNHEntity mergedItem = session.Merge(ormItem); 
       transaction.Commit(); 
      } 
     } 

.Merge est une chose merveilleuse. Entity Framework ne l'a pas. Huer.

Est-ce beaucoup de configuration? Oui. Est-ce que je pense que c'est parfait? No.

Cependant.Parce que j'envoie des DTO très basiques (Poco's) qui ne sont pas "aromatisés" à l'ORM, j'ai la possibilité de changer d'ORM sans tuer mes contrats avec le monde extérieur.

Mon datalayer peut être ADO.NET, EF, NHibernate ou n'importe quoi. Je dois écrire les "convertisseurs" si je commute, et le code ORM, mais tout le reste est isolé.

Beaucoup de gens se disputent avec moi. Ils ont dit que je faisais trop, et les Entités ORM vont bien.

Encore une fois, j'aime "maintenant autoriser tout chargement paresseux". Et je préfère que ma couche de données soit isolée. Mes clients ne devraient pas savoir ou se soucier de ma couche de données/orme de choix.

Il y a juste assez de différences subtiles (ou pas si subtiles) entre EF et NHibernate pour débloquer le plan de jeu.

Est-ce que mes objets Domain-DTO-Object ressemblent à 95% comme mes entités ORM? Oui. Mais c'est le 5% qui peut vous visser.

Le déplacement à partir de DataSets, en particulier si elles sont remplies à partir de procédures stockées avec beaucoup de biz-logic dans le TSQL, n'est pas trivial. Mais maintenant que je fais le modèle objet, et que je n'écris jamais une procédure stockée qui ne soit pas de simples fonctions CRUD, je ne reviendrai jamais.

Et je déteste les projets de maintenance avec voodoo TSQL dans les procédures stockées. Ce n'est plus 1999. Eh bien, la plupart des endroits.

Bonne chance.

PS Sans .Merge (dans EF), voici ce que vous avez à faire dans un monde déconnecté: (boo microsoft)

http://www.entityframeworktutorial.net/EntityFramework4.3/update-many-to-many-entity-using-dbcontext.aspx

+0

Donc, je peux comprendre les points ici sur ne pas exposer des entités à travers mes services. Cependant, une pièce majeure que j'essayais de réaliser était d'envoyer seulement un diff au serveur et non à l'ensemble de l'objet. C'était simple (même s'il était couplé) en utilisant DataSets. –

Questions connexes