27 votes

NHibernate fluide, fonctionnant avec des interfaces

Je viens de passé à parler Couramment NHibernate et j'ai rencontré un problème et je n'ai trouvé aucune information à ce sujet.

Voici le cas :

public class Field : DomainObject, IField
{
    public Field()
    {  
    }

    public virtual string Name { get; set; }
    public virtual string ContactPerson { get; set; }
    public virtual bool Private { get; set; }
    public virtual IAddress Address { get; set; }  
}

IAddress est une interface implémentée par une classe nommée Adresse

public class Address : DomainObject, IAddress
{
    public Address()
    {
    }

    public virtual string City { get; set; }
    public virtual string Country { get; set; }
    public virtual string PostalCode { get; set; }
    public virtual string StreetAddress { get; set; }
}

Voici mes fichiers de mappage pour les deux classes

ADRESSE

public class AddressMap : ClassMap<Address>
{   
    public AddressMap()
    {
        WithTable("Addresses");
        Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid();
        Map(x => x.City, "City");
        Map(x => x.Country, "Country");
        Map(x => x.PostalCode, "PostalCode");
        Map(x => x.StreetAddress, "StreetAddress");
    }
}

CHAMP

public class FieldMap : ClassMap<Field>
{
    public FieldMap()
    {
        WithTable("Fields");
        Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid();
        Map(x => x.Name, "Name");
        Map(x => x.ContactPerson, "ContactPerson");
        Map(x => x.Private, "Private");
        References(x => x.Address, "AddressId").Cascade.Delete().Cascade.SaveUpdate();
    }
}

Alors, quand j'ai essayé de restauration d'un objet de champ de ma base de données, j'obtiens une NHibernate message d'erreur qui indique que IAddress n'est pas tracé. Est-il possible de spécifier à NHibernate pour utiliser la classe d'Adresse dans la cartographie?

S'il vous plaît laissez-moi savoir si plus d'informations sont nécessaires.

Merci beaucoup,

Charles

33voto

cbp Points 9676

Je trouve qu'il y a des raisons valables pour l'utilisation d'une interface à la place d'un béton de classe en tant que propriété.

Par exemple, si votre Champ de classe a dans un autre projet à la classe d'Adresse, et vous n'avez pas une dépendance à la classe d'Adresse du projet à partir de la classe de Champ du projet.

Il existe d'autres moyens de faire face à cette situation, mais la façon la plus simple est souvent de tenter ce que vous faites et explicitement dire NHibernate la classe de béton à utiliser pour IAddress.

Vous pouvez désormais le faire dans NHibernate Fluent, comme ceci:

References(x => x.Address, "AddressId")
    .Class(typeof(Address);

Malheureusement, vous ne pouvez pas faire cela avec HasMany ou HasManyToMany. Je ne sais pas si ce serait même possible en raison du manque de bonne covariance de soutien en C#.

5voto

Luke Points 1169

Sur votre Champ objet, vous avez un objet de type IAddress. Cela pourrait être mis en œuvre par un certain nombre de différentes implémentations. Avec ce que vous demandez, chaque application a son propre cartographie, qui permettrait d'introduire n'importe quel nombre de difficultés (impossible?) pour NHibernate à manipuler.

Un exemple simple serait de les aider à démontrer. Disons que vous avez deux IAddress implémentations Ip1 et Ip2. Ils sont enregistrés dans leur propre table, tblAddress1, et tblAddress2. Lorsque vous essayez de charger votre Champ objet, tous les NHibernate sait, c'est que vous avez quelque chose qui met en œuvre IAddress, il ne sait pas laquelle de mise en œuvre a été conservée. Comment serait-il savoir qui de la cartographie à utiliser pour récupérer l'objet enfant pour n'importe quel domaine donné?

Je suis sûr qu'il y a plus de complications, mais cet exemple montre pourquoi vous devez avoir un mappage pour le type exact de l'objet que vous avez déclaré.

0voto

Stumblor Points 372

Si vous souhaitez découpler entièrement votre ORM de votre couche de domaine et référencer des interfaces dans votre couche de données plutôt que de spécifier des classes concrètes, vous pouvez implémenter un EmptyInterceptor à mapper entre les deux.

Voir ma réponse ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X