Fluent NHibernate, travailler avec des interfaces

Je viens de passer à Fluent 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();
    }
}

Donc, quand j'ai essayé de récupérer un objet field à partir de ma base de données, j'obtiens une erreur NHibernate qui indique que IAddress n'est pas mappé. Est-il possible d' spécifiez à NHibernate pour utiliser la classe D'adresse dans le mappage?

Veuillez me faire savoir si plus d'informations sont nécessaires.

Merci beaucoup,

Charles

31
demandé sur harriyott 2009-03-23 05:10:57

3 réponses

Je trouve qu'il existe des raisons valables d'utiliser une interface au lieu d'une classe concrète en tant que propriété.

Par exemple, si votre classe de champ était dans un projet distinct de la classe D'adresse, et que vous n'aviez pas de dépendance sur le projet de la classe D'adresse du projet de la classe de champ.

Il existe d'autres façons de gérer cette situation, mais le moyen le plus simple est souvent d'essayer ce que vous faites et de dire explicitement à NHibernate la classe concrète à utiliser IAddress.

Vous pouvez maintenant le faire en Fluent NHibernate, comme ceci:

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

Malheureusement, vous ne pouvez pas le faire avec HasMany ou HasManyToMany. Je ne suis pas sûr si cela serait même possible en raison du manque de bon support de covariance en C#.

35
répondu cbp 2010-01-22 00:28:59

Sur votre objet Field, vous avez un objet de type IAddress. Cela pourrait être implémenté par n'importe quel nombre d'implémentations différentes. Avec ce que vous demandez, chaque implémentation aurait sa propre cartographie, ce qui introduirait un certain nombre de difficultés (impossibilités?) pour NHibernate à gérer.

Un exemple simple aiderait à démontrer. Disons que vous avez deux implémentations Iaddress Address1 et Address2. Ils sont chacun enregistrés dans leur propre table, tblAddress1, et tblAddress2. Lorsque vous essayez de charger votre objet Field, Tout ce que NHibernate sait, C'est que vous avez quelque chose qui implémente IAddress, il ne sait pas quelle implémentation a été persistante. Comment saurait-il quel mappage utiliser pour récupérer l'objet enfant pour un champ 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 d'objet que vous avez déclaré.

5
répondu Luke 2009-03-25 20:41:37

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

Voir ma réponse ici.

0
répondu Stumblor 2017-05-23 11:46:59