Отображение один в один в FluentNHibernate, NHibernate пытается написать дочерний, прежде чем родительский - PullRequest
1 голос
/ 13 марта 2012

Я пытаюсь установить отношения 1: 1 в ФН, но это немного болезненно.

Я посмотрел на http://avinashsing.sunkur.com/2011/09/29/how-to-do-a-one-to-one-mapping-in-fluent-nhibernate/, который, казалось, подтвердил, что это должно работать, но эй, он продолжает пытаться вставить записи в дочерние таблицы до родительского, что означает, что дочерние вставки не содержат CustomerId, который требуется как это ограничение внешнего ключа.

Таблица

   +-----------------------+      +----------------------+
   | tblCustomer           |      |  tblCustomerPhoto    |
   |-----------------------|      |----------------------|
   |                       | 1:1  |                      |
   | CustomerID (PK)       |+---->|  CustomerID (FK)     |
   | OtherJunk...          |      |  Photo (Image)       |
   |                       |      |                      |
   |                       |      |                      |
   +-----------------------+      +----------------------+

Модель

public class Customer 
{
    public virtual int CustomerID { get; private set; }
    /* public virtual Other stuff */
}

public class CustomerPhoto
{
    public virtual int CustomerID { get;set;}
    public virtual Byte[] Photograph { get; set; }
}

Карты

public class CustomerPhotoMap : ClassMap<CustomerPhoto>
{
    public CustomerPhotoMap()
    {
        Id(x => x.CustomerID)
            .Column("CustomerID")
            .GeneratedBy.Assigned();

        Map(x => x.Photograph)
            .CustomSqlType("Image")
            .CustomType<Byte[]>()
            .Nullable();
    }
}

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {

        Id(x => x.CustomerID)
            .GeneratedBy.Identity()
            .Column("CustomerID");
        HasOne<CustomerPhoto>(x => x.CustomerPhoto)
            .LazyLoad()
            .ForeignKey("CustomerID");
    }
}

Тест

class CustomerMappingFixture : IntegrationTestBase
{
    [Test]
    public void CanMapCustomer()
    {
        new PersistenceSpecification<Customer>(Session)
            .CheckReference(x => x.CustomerPhoto, new CustomerPhoto(){ Photograph = Arrange.GetBitmapData(ImageFormat.Jpeg) })
            .VerifyTheMappings();
    }
}

Теперь для столбца внешнего ключа на CustomerPhoto было установлено значение not-null, и я повторял это в нотации на CustomerPhotoMapping. На основе (https://stackoverflow.com/a/2286491/529120) я изменил это на nullable и удалил обозначения из отображения.

Независимо от того, возвращается NHibernate System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта.

и, кажется, пытается сначала вставить запись CustomerPhoto, передавая ноль в качестве CustomerId; затем создайте запись о клиенте, затем попытайтесь выбрать клиента и фотографию, используя левое внешнее соединение. Который, очевидно, не будет работать, так как ни разу не попытался обновить идентификатор в таблице фотографий.

1 Ответ

2 голосов
/ 14 марта 2012

Мало что я заметил

  1. Использование CheckReference для проверки этого сопоставления, вероятно, неверно.Я почти уверен, что это только для отношений «многие к одному».Поэтому имеет смысл, что он пытается вставить CustomerPhoto перед Customer.Я бы написал тест, используя прямые сессии NH здесь.Я обнаружил, что для многих из моих сопоставлений, которые были нетривиальными, было бы гораздо сложнее использовать PersistenceSpecification.
  2. Отображения «один на один» выглядели так, как будто они немного отклонены (предлагаемое решение ниже)
  3. При отображении столбца изображения в байтовый массив я не думаю, что нужно объявлять пользовательский тип.Отображение ниже работало хорошо для меня.Я думаю, что другие вещи, которые у вас есть в этом сопоставлении свойств, не нужны.

У меня есть сопоставление, почти идентичное вашему, и вот что я использую:

public class Customer 
{
  public virtual int CustomerID { get; private set; }
  public virtual CustomerPhoto CustomerPhoto { get; set; }
  /* public virtual Other crap */

}

public class CustomerPhoto
{
  public virtual Customer Customer { get; set; }
  public virtual Byte[] Photograph { get; set; }
}

public class CustomerPhotoMap : ClassMap<CustomerPhoto>
{
    public CustomerPhotoMap()
    {
        Id(x => x.Id)
            .Column("CustomerID")
            .GeneratedBy.Foreign("Customer");

        Map(x => x.Photograph).Length(Int32.MaxValue);
    }
}

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {

        Id(x => x.CustomerID).GeneratedBy.Identity()
            .Column("CustomerID");

        HasOne(x => x.CustomerPhoto)
            .Cascade.All();

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...