Свободный NHibernate, работа с интерфейсами - PullRequest
31 голосов
/ 23 марта 2009

Я только что переключился на Fluent NHibernate, и у меня возникла проблема, и я не нашел никакой информации о ней.

Вот случай:

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 - это интерфейс, реализованный классом с именем Address

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; }
}

Вот мои файлы сопоставления для обоих классов

АДРЕС

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");
    }
}

Область

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();
    }
}

Поэтому, когда я пытался извлечь объект поля из моей базы данных, я получаю ошибку NHibernate, которая утверждает, что IAddress не отображается. Есть ли способ указать NHibernate использовать класс Address в отображении?

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Большое спасибо,

Чарльз

Ответы [ 3 ]

36 голосов
/ 22 января 2010

Я считаю, что существуют веские причины для использования интерфейса вместо конкретного класса в качестве свойства.

Например, если ваш класс Field находился в отдельном проекте для класса Address, и у вас не было зависимости от проекта класса Address от проекта класса Field.

Существуют и другие способы справиться с этой ситуацией, но наиболее простым способом часто является попытка сделать то, что вы делаете, и объяснение NHibernate конкретному классу для использования с IAddress.

Теперь вы можете сделать это в Fluent NHibernate, например:

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

К сожалению, вы не можете сделать это с HasMany или HasManyToMany. Я не уверен, возможно ли это даже из-за отсутствия хорошей поддержки ковариации в C #.

5 голосов
/ 25 марта 2009

В вашем объекте Field у вас есть объект типа IAddress. Это может быть реализовано любым количеством различных реализаций. С учетом того, что вы спрашиваете, каждая реализация будет иметь свое собственное отображение, которое будет представлять любое количество трудностей (невозможностей?) Для обработки NHibernate.

Простой пример поможет продемонстрировать. Скажем, у вас есть две реализации IAddress Address1 и Address2. Каждый из них сохраняется в своей собственной таблице, tblAddress1 и tblAddress2. Когда вы пытаетесь загрузить объект Field, все, что NHibernate знает, это то, что у вас есть что-то, что реализует IAddress, оно не знает, какая реализация была сохранена. Как он узнает, какое отображение использовать для извлечения дочернего объекта для любого заданного поля?

Я уверен, что есть и другие сложности, но этот пример показывает, почему вы должны иметь отображение для точного типа объекта, который вы объявили.

0 голосов
/ 17 февраля 2014

Если вы заинтересованы в том, чтобы полностью отделить ORM от уровня вашего домена и ссылаться на интерфейсы по всему уровню данных, а не указывать конкретные классы, вы можете реализовать EmptyInterceptor для отображения между ними.

Смотрите мой ответ здесь .

...