Fluent NHibernate, работающий с интерфейсами
Я просто переключился на 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; }
}
Здесь мои файлы сопоставления для обоих классов
ADDRESS
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 в сопоставлении?
Пожалуйста, дайте мне знать, нужна ли дополнительная информация.
Большое спасибо,
Чарльз
Ответы
Ответ 1
Я обнаружил, что существуют веские причины использования интерфейса вместо конкретного класса как свойства.
Например, если ваш класс Field был в отдельном проекте классу Address, и у вас не было зависимости от проекта класса Address из проекта класса Field.
Есть другие способы справиться с этой ситуацией, но самый простой способ - это часто пытаться выполнить то, что вы делаете, и объяснять, что NHibernate использует конкретный класс для IAddress.
Теперь вы можете сделать это в Fluent NHibernate, например:
References(x => x.Address, "AddressId")
.Class(typeof(Address);
К сожалению, вы не можете сделать это с помощью HasMany или HasManyToMany. Я не уверен, что это возможно даже из-за отсутствия хорошей ковариационной поддержки на С#.
Ответ 2
В вашем полевом объекте у вас есть объект типа IAddress. Это может быть реализовано любым количеством различных реализаций. С тем, что вы просите, каждая реализация будет иметь свое собственное сопоставление, которое приведет к возникновению любого количества трудностей (невозможностей?) Для NHibernate для обработки.
Простой пример поможет продемонстрировать. Скажем, у вас есть две реализации IAddress Address1 и Address2. Каждый из них сохраняется в своей таблице, tblAddress1 и tblAddress2. Когда вы пытаетесь загрузить свой объект Field, все, что NHibernate знает, что у вас есть что-то, что реализует IAddress, он не знает, какая реализация была сохранена. Как узнать, какое сопоставление используется для извлечения дочернего объекта для любого заданного поля?
Я уверен, что есть больше осложнений, но этот пример показывает, почему вы должны иметь сопоставление для определенного типа объекта, который вы объявили.
Ответ 3
Если вы заинтересованы в том, чтобы полностью отключить ORM от вашего уровня домена и ссылаться на интерфейсы на вашем уровне данных, а не на конкретные классы, вы можете реализовать EmptyInterceptor для сопоставления между ними.
Смотрите мой ответ здесь.