2009-11-10 5 views
4

J'utilise Fluent NHibernate pour faire mes mappings NHibernate, mais maintenant je suis arrivé à un problème que je ne suis pas sûr de savoir comment résoudre. Une version simplifiée du problème suit.Comment mettre à jour des champs spécifiques de classe dans Fluent NHibernate sans mettre à jour l'ensemble de l'objet?

J'ai une classe d'utilisateurs:

public class User { 
    public virtual int Id { get; set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 
} 

C'est associé Fluent NHibernate classe Carte

public class UserMap : ClassMap<User> { 
    public UserMap() { 
     Id(x => x.Id); 
     Map(x => x.FirstName); 
     Map(x => x.LastName); 
    } 
} 

J'ai deux formes web. Un formulaire me permet de changer le prénom des utilisateurs, et le second formulaire me permet de changer le nom de famille des utilisateurs. Ce que je suis en train de réaliser est une instruction SQL simple comme ceci:

Pour la première forme:
UPDATE [users] SET firstname='new first name' WHERE id=1

Pour la deuxième forme:
UPDATE [users] SET lastname='new last name' WHERE id=1

Actuellement NHibernate effectue l'instruction SQL suivante sur mon La base de données:
UPDATE [users] SET firstname=null, lastname='new last name' WHERE id=1

Le problème dans l'application du monde réel, c'est qu'il y en a trop propriétés à mettre à jour sur certains gros objets (ainsi que les restrictions d'accès), et il semble inutile de mettre à jour l'objet entier, quand tout ce que je veux/je suis autorisé à faire est de mettre à jour une seule propriété. Je souhaite que quelqu'un puisse fournir des conseils sur la façon dont je peux réaliser ceci, ou me diriger dans la bonne direction pour résoudre ceci.

+0

Voir ici pour plus de discussions: http://stackoverflow.com/questions/1243390/what-is-the-best-approach-to-update-only-changed-properties-in-nhibernate-when- se. En outre, je ne comprends pas vraiment pourquoi vous allez échanger la simplicité et faire beaucoup de travaux manuels tout de suite - avez-vous essayé la solution? La mise à jour dynamique ne fonctionnera-t-elle pas pour vous (mapping.DynamicUpdate() dans FNH)? – queen3

+0

Je viens de vérifier mon code. J'ai exporté les mappages FNH et les mises à jour dynamiques sont activées, mais cela ne semble pas faire de différence. Il suffit de réécrire mon dépôt pour pouvoir utiliser la même session et voir si sélectionner avant la mise à jour fait une différence. –

Répondre

0

Hibernate fait la bonne chose, mais votre problème indique que votre schéma a besoin d'être normalisé.

+0

Merci pour le commentaire Mcwafflestix. Je ne suis pas sûr d'avoir posé la question correctement, juste pour confirmer que je ne suis pas trop préoccupé par la normalisation, dans mon cas c'est un compromis de performance par conception. La dénormalisation a de nombreux avantages lorsqu'elle est utilisée correctement. ;-).En dehors des problèmes de "normalisation", pourriez-vous proposer des solutions possibles pour optimiser les requêtes NHibernate? –

+0

En général, je suggère toujours la normalisation. Voici la chose; Vous avez raison, les tables non normalisées peuvent avoir de nombreux avantages, mais l'un des inconvénients de leur utilisation est qu'il peut être difficile de personnaliser les solutions prêtes à l'emploi (comme Hibernate) pour elles. Je suggère que vous devez peser vos compromis; est-il plus important de maintenir votre base de données dénormalisée (et de personnaliser les accès à la table de Hibernate) que de normaliser votre schéma (et de pouvoir utiliser Hibernate "tel quel")? Vous seul pouvez prendre cette décision. Je serais du côté de la «normaliser» la fin des choses. –

0

Ok, ça marche, Merci pour l'aide et les conseils Queen3!

voici comment je sovled il:

using (var sf = Repository.CreateSessionFactory()) { 
    using (var s = sf.OpenSession()) { 
     using (var t = session.BeginTransaction()) { 
      var existingUser = s.Get<User>(editedUser.Id); 
      existingUser.LastName = editedUser.LastName; 
      s.SaveOrUpdate(existingUser); 
      t.Commit(); 
     } 
    } 
} 

Bien que cela fonctionne, il faut que je récupère l'utilisateur de la première base de données et le travail au sein de la même session. La bonne chose est que l'instruction sql générée met juste à jour le champ dirty LastName. :-)

Je suis incapable de le faire fonctionner avec une instance détachée de l'utilisateur, c'est similaire à la façon dont je le faisais auparavant, ce qui a entraîné la mise à jour de tous les champs de l'utilisateur.

using (var sf = Repository.CreateSessionFactory()) { 
    using (var s = sf.OpenSession()) { 
     using (var t = session.BeginTransaction()) { 
      s.SaveOrUpdate(editedUser); 
      t.Commit(); 
     } 
    } 
} 
Questions connexes