2009-04-21 4 views
1

J'ai une relation un-à-plusieurs, mais j'aimerais que seule une instance ait une relation un-à-un.Mappage hbm.xml

J'ai des véhicules de classe qui peuvent avoir plusieurs propriétaires tout au long de leur vie. Je veux seulement cartographier la classe pour obtenir les actifs. Y a-t-il un moyen de le faire?

Le problème est dans le fichier hbm.xml. Un véhicule peut avoir plusieurs propriétaires tout au long de leur vie, mais je ne veux obtenir que le dernier propriétaire. J'ai besoin de filtrer par vehiculeId, ownerId et EndDate. Je veux remplir le propriétaire de l'objet qui est dans vehicle.cs avec les actifs. Quand j'écris: Vehicule v = VehiculeService.SearchVehicule (id);

J'aimerais que v.Owner contienne le propriétaire du dernier véhicule.

Je ne peux pas enregistrer l'ID du propriétaire sur la table du véhicule parce que le propriétaire dépend de la date. Je peux avoir par exemple: propriétaire du véhicule StartDate EndDate 1 1 04/04/2009 04/10/2009 1 2 05/10/2009 NULL

Pour cette raison, je dois filtrer par EndDate avoir les actifs

J'ai trois tables: Vehicle, Owner et VehicleVehicle. Le problème est que je dois une référence dans vehicle.cs au propriétaire actuel. Et je ne sais pas comment faire la cartographie.

Toute aide serait appréciée. Merci

Répondre

0

Un moyen facile de mapper cela est de le transformer en une relation de plusieurs à un, et de stocker l'ID du propriétaire actuel sur la table du véhicule. Je comprends que cela pourrait être un changement de schéma.

Une façon de tromper ce serait de créer une vue qui serait essentiellement la table du véhicule, plus il tirerait le propriétaire actuel. De cette façon, vous n'avez pas besoin de modifier le schéma, vous devez alors mapper à la vue au lieu de la table. Je ne suis pas sûr si la définition de votre propre chargeur fonctionnerait dans ce cas mais c'est une option de plus à explorer.

Modifier

Je comprends votre prédiction. Le moyen le plus simple serait de modifier le schéma et l'application pour ajouter cette colonne supplémentaire à une fausse image avec une vue. Ainsi par exemple

select vehicle.*, owner.ownerid 
from vehicle 
inner join owner 
    on owner.vehicleid=vehicle.vehicle 
and owner.enddate is null 

Je suppose que le propriétaire actuel a une date de fin nulle. Maintenant, vous modifiez votre mappage pour mapper à la vue au lieu de la table. Oui c'est un hack mais ça marchera.

Je suppose que vous avez encore besoin d'être mappé dans nHibernate? Une autre option consisterait à ajouter un filtre where sur le mappage de classe du propriétaire pour filtrer où la date de fin est nulle.

Une autre option consiste à charger tous les propriétaires et à appliquer la règle métier qui définit le propriétaire actuel au niveau de l'application. Votre objet pourrait ressembler à:

public Owner CurrentOwner 
{ 
    get 
    { 
     return _owners.Find(o=>o.EndDate==DateTime.Min); //Or null if your using a nullable datetime 
    } 
    set 
    { 
     CurrentOwner.EndDate=DateTime.Now; 
     _owners.Add(value); 
    } 
} 

}

+0

Je ne peux pas stocker l'ID du propriétaire sur la table du véhicule parce que le propriétaire dépend de la date. Je peux avoir par exemple: propriétaire du véhicule StartDate EndDate 1 1 04/04/2009 04/10/2009 1 2 05/10/2009 NULL Pour cette raison, je dois filtrer par EndDate avoir les actifs –

0

Vous pouvez utiliser un des critères (ou DetachedCriteria pour le printemps) objet de restreindre les valeurs supplémentaires lors de l'exécution des recherches.

0

Je suggère de conserver cette référence dans la couche de gestion et de la mapper en tant que relation plusieurs-à-un. Je veux dire que vous définissez cette référence explicitement dans votre code. Cela vous permet également de trouver des véhicules par ses propriétaires actuels tout droit.

Exemple:

<class name="Vehicle"> 
    <map name=AllOwners" > 
    ... 
    </map> 

    <many-to-one name="CurrentOwner" ...> 
</class> 

public class Vehicle 
{ 
    IList<Owner> AllOwners { get; private set; } 
    Owner CurrentOwner { get; set; } 
} 

public void SetNewOwner(Vehicle v, Owner o) 
{ 
    v.AllOwners.Add(o); 
    v.CurrentOwner = o; 
} 
+0

je l'ai déjà avoir une référence au propriétaire dans mon véhicule de classe, donc vehicle.owner apparaît de tous les côtés dans mon code. Quand j'écris Vehicle v = VehicleService.Search (id); Comment le véhicule se remplit-il? –

+0

Voulez-vous dire: "comment v.AllOwners est-il rempli"? NHibernate crée un PersistentBag ou quelque chose et l'assigne au setter (privé) de la propriété. Vous ne pouvez pas accéder à la liste dans le setter de la propriété, car il n'est probablement pas encore initialisé. –

0

Votre relation est en fait beaucoup à plusieurs

Un propriétaire peut posséder plusieurs véhicules

Je garderais les véhicules et les propriétaires séparés et gérer leur relation dans une autre entité En d'autres termes, vous avez besoin de trois tables

Vous ne savez pas si j'ai modifié votre question ou fourni une réponse :)

+0

J'ai déjà trois tables: Vehicle, Owner et OwnerVehicle. Le problème est que je dois une référence dans vehicle.cs au propriétaire actuel. Et je ne sais pas comment faire la cartographie. –

0

Je ne pense pas qu'il soit possible que NHibernate veuille charger la propriété "Owner" automatiquement. Cependant, vous devriez être capable d'écrire une requête pour obtenir le propriétaire actuel d'un véhicule. Il semble que vous ayez déjà un dépôt/service de véhicule avec VehiculeService. Je voudrais ajouter une méthode comme GetCurrentOwner() qui prend un paramètre, l'ID du véhicule. Ensuite, demandez à votre propriété Vehicle.Owner d'appeler cette méthode en transmettant son propre ID.

Une requête par critères pourrait ressembler à ceci:

session.CreateCriteria(typeof(Owner)) 
    .CreateCriteria("OwnedVehicles") // Property path to the OwnerVehicle join table 
     .Add(Expression.IsNull("EndDate")) 
     .CreateCriteria("Vehicle") 
      .Add(Expression.IdEq(id)) 
      .UniqueResult<Owner>();