8

я следующие 2 класса:Fluent NHibernate один-ко-многим

объявления

public virtual int Id { get; set; 
public virtual IList<AdvertImage> AdvertImages { get; set; } 

AdvertImage

public virtual int Id { get; set; } 
public virtual string Filename { get; set; 
public virtual Advert Advert { get; set; } 

В БД, моя таблица AdvertImages имеет FK 'AdvertId', который относится к таблице Adverts, которая имеет PK идентификатора.

Это сопоставление «один-ко-многим», поскольку одно объявление может иметь много изображений.

Моего Fluent NHibernate отображение (отредактированное для краткости) является:

AdvertMap

Id(x => x.Id) 
    .GeneratedBy.Identity(); 
... 
HasMany(x => x.AdvertImages) 
    .KeyColumn("AdvertId") 
    .Inverse(); 
... 
Table("Adverts"); 

AdvertImageMap

Id(x => x.Id) 
    .GeneratedBy.Identity(); 
... 
References(x => x.Advert) 
    .Column("AdvertId"); 
... 
Table("AdvertImages"); 

Я создаю новый экземпляр Advert в коде, затем заполнение AdvertImages prope rty (из объявления) с List<AdvertImage>.

Когда я иду, чтобы сохранить свой объект Advert в БД, я хотел бы, чтобы объявления были помещены в их таблицу AdvertImages, но из-за взаимосвязи между двумя таблицами мне сначала нужно, чтобы вставка рекламы произошла, так что генерируется идентификатор PK, который затем может быть вставлен в таблицу AdvertImages. (Когда я создаю свой список AdvertImage, я заполняю свойство Filename, но, очевидно, на этом этапе нет нового объявления, поэтому хочу, чтобы это было заполнено, когда объявление сохраняется в БД).

Я пробовал экспериментировать с различными настройками Inverse() и Cascade, но пока не удалось. Может ли кто-нибудь помочь?

ответ

10

Вам нужно изменить Advert отображение в каскаде:

Id(x => x.Id) 
    .GeneratedBy.Identity(); 

HasMany(x => x.AdvertImages) 
    .KeyColumn("AdvertId") 
    .Inverse() 
    .Cascade.AllDeleteOrphan(); 

Table("Adverts"); 

Затем вы должны быть в состоянии сделать что-то подобное, чтобы упорствовать в Advert объект и это дети AdvertImage.

Advert newAdvert = new Advert(); 
AdvertImage newImage = new AdvertImage(); 
newImage.Advert = newAdvert; 
newAdvert.AdvertImages.Add(newImage); 

using(NHibernate.ISession session = SessionFactory.GetCurrentSession()) 
{ 
    using (NHibernate.ITransaction tran = session.BeginTransaction()) 
    { 
     session.Save(newAdvert); 
     tran.Commit(); 
    } 
} 

Мои объекты обычно содержат Добавление и удаление методов двунаправленной один ко многим отношений, как это:

public class Advert 
{ 
    public virtual IList<AdvertImage> AdvertImages { get; set; } 

    public virtual void AddImage(AdvertImage newImage) 
    { 
     newImage.Advert = this; 
     AdvertImages.Add(newImage); 
    } 
} 
+0

Спасибо Cole W и приветствуем советы по методам добавления и удаления. – marcusstarnes

1

Обычно для меня обычно нужно установить столбец внешнего ключа, чтобы разрешить нули в БД - это будет ваш столбец AdWordsIde, но я не уверен, что это будет работать в вашем случае, поскольку вы используете идентификатор. Что NHibernate делает, это INSERT все с одним запросом, а затем обновляет столбец внешнего ключа дочерней таблицы с правильным идентификатором родительской таблицы. Возможно, это сработает и в вашем случае.

Вот некоторые подобный вопрос, который может помочь: Cascade insert on one-to-many with fluent NHibernate

+1

Эта ссылка, которую вы включили, не имеет никакого смысла, поскольку она не имеет никакого отношения к 'Fluent NHibernate'. – Komengem

+0

@ KomengeMwandila Хотя ответ на вопрос, который я связал, не использует Fluent NHibernate, вопрос делает. Кроме того, Fluent NHibernate не добавляет ничего нового здесь. Он просто предоставляет другой интерфейс для сопоставления NHibernate. Как только вы поймете, как работает сопоставление, вы можете применить его к Fluent NHibernate, XML-сопоставлению, сопоставлению по коду ... –

2

Я была такая же проблема. Я провел некоторое время, пытаясь использовать различные типы картографирования.Затем я обнаружил, что мои сопоставления прекрасны, и на самом деле мне нужно было провести сеанс в транзакции и использовать метод Commit() после метода session.SaveOrUpdate().

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{ 
// execute code that uses the session 
tx.Commit(); 
} 
+0

спасибо ..save много времени, копая вокруг этой проблемы –