Подтвердить что ты не робот

Fluent NHibernate: как создать двунаправленное сопоставление "один ко многим"?

Основной вопрос. Как создать двунаправленную карту "один ко многим" в Fluent NHibernate?

Детали:

У меня есть родительский объект с большим количеством детей. В моем случае для ребенка не имеет смысла не иметь родителя, поэтому в базе данных я бы хотел, чтобы внешний ключ для родителя имел ограничение NOT NULL. Я автоматически генерирую свою базу данных из сопоставления Fluent NHibernate.

У меня есть родительский элемент с множеством дочерних объектов:

public class Summary
{
   public int id {get; protected set;}

   public IList<Detail> Details {get; protected set;}
}

public  class Detail
{
   public int id {get; protected set;}

   public string ItemName {get; set;}

  /* public Summary Owner {get; protected set;} */ //I think this might be needed for bidirectional mapping?
}

Вот отображение, с которого я начал:

public class SummaryMap : ClassMap<Summary>
{
    public SummaryMap()
    {
        Id(x => x.ID);

        HasMany<Detail>(x => x.Details);
    }
}

public class DetailMap : ClassMap<Detail>
{
    public DetailMap()
    {
        Id(x => x.ID);

        Map(x => x.ItemName).CanNotBeNull();
    }
}

В таблице Detail, Summary_id должен быть Not Null, потому что в моем случае бессмысленно иметь объект Detail, не привязанный к итоговый объект. Тем не менее, только использование карты HasMany() оставляет заниженный ключ Summary_id недействительным.

Я нашел в документах NHibernate (http://www.hibernate.org/hib_docs/nhibernate/html/collections.html): "Если требуется родительский элемент, используйте двунаправленную связь" один-ко-многим "".

Итак, как мне создать двунаправленную карту "один ко многим" в Fluent NHibernate?

4b9b3361

Ответ 1

Чтобы получить двунаправленную связь с не-нулевым столбцом внешнего ключа в таблице "Сведения", вы можете добавить предлагаемое свойство "Владелец", сопоставление "Ссылки" (...). CanNotBeNull() в классе "DetailsMap" и сделать конец сводной информации обратный.

Чтобы избежать двух разных столбцов внешнего ключа для двух направлений ассоциации, вы можете указать имена столбцов вручную или назвать свойства таким образом, чтобы они указывали одинаковое имя столбца для обоих направлений. В этом случае вы предлагаете переименовать свойство Details.Owner в Details.Summary.

Я сделал идентификатор Summary, сгенерированный с помощью инкремента, чтобы избежать проблем при вставке в таблицу, так как Summary currenty не имеет столбцов, кроме id.

Домен:

public class Detail
{
    public int id { get; protected set; }
    public string ItemName { get; set; }

    // Renamed to use same column name as specified in the mapping of Summary.Details
    public Summary Summary {get; set;} 
}

public class Summary
{
    public Summary()
    {
        Details = new List<Detail>();
    }

    public int id { get; protected set; }
    public IList<Detail> Details { get; protected set; }
}

Mapping:

public class DetailMap : ClassMap<Detail>
{
    public DetailMap()
    {
        Id(x => x.id)
            .GeneratedBy.Native();

        Map(x => x.ItemName)
            .CanNotBeNull();

        References<Summary>(x => x.Summary)
            // If you don't want to rename the property in Summary,
            // you can do this instead:
            // .TheColumnNameIs("Summary_id")
            .CanNotBeNull();
    }
}

public class SummaryMap : ClassMap<Summary>
{
    public SummaryMap()
    {
        Id(x => x.id)
            .GeneratedBy.Increment();

        HasMany<Detail>(x => x.Details)
            .IsInverse()
            .AsBag(); // Use bag instead of list to avoid index updating issues
    }
}