Свободный Nhibernate, отображающий несколько классов в один внешний ключ - PullRequest
1 голос
/ 11 ноября 2010

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

Например:

TABLE Person
PersonId int
Name varchar
ShirtId int

TABLE Shirt
ShirtId int
Color string

TABLE SpecialShirt
ShirtId int
Sleeves int

Классы выглядят так:

public class Person
{
    public virtual int PersonId { get; set; }
    public virtual string Name { get; set; }
    public virtual Shirt Shirt { get; set; }
    public virtual SpecialShirt SpecialShirt { get; set; }
}

public class Shirt
{
    public Shirt()
    {
        PersonList = new List<Person>();
    }

    public virtual int ShirtId { get; set; }
    public virtual string Color { get; set; }
    public virtual IList<Person> PersonList { get; set; }
    public virtual void AddPerson(Person p)
    {
        PersonList.Add(p);
    }
}

public class SpecialShirt : Shirt
{
    public virtual int Sleeves { get; set; }
}

И отображения выглядят так:

public class TestPersonMap : ClassMap<TestPerson>
{
    public TestPersonMap()
    {
        Table("TestPerson");
        Id(x => x.PersonId).GeneratedBy.Native();
        Map(x => x.Name);
        References(x => x.Shirt).Column("ShirtId");
        References(x => x.SpecialShirt).Column("ShirtId"); // commenting out this line works
    }
}

public class TestShirtMap : ClassMap<TestShirt>
{
    public TestShirtMap()
    {
        Table("TestShirt");
        Id(x => x.ShirtId).GeneratedBy.Native();
        Map(x => x.Color);
        HasMany(x => x.PersonList).KeyColumn("ShirtId").Inverse().Cascade.All();
    }
}

public class TestSpecialShirtMap : SubclassMap<TestSpecialShirt>
{
    public TestSpecialShirtMap()
    {
        Table("TestSpecialShirt");
        KeyColumn("ShirtId");
        Map(x => x.Sleeves).Column("Sleeves");
    }
}

Затем я пытаюсь сохранить новый экземпляр Person and Shirt следующим образом:

var shirt1 = new TestShirt() {Color = "Red"};
var person1 = new TestPerson() {Name = "Fred Person", Shirt = shirt1};
shirt1.AddPerson(person1);

session.Save(shirt1);
session.Save(person1);

Этот код получает следующую ошибку:

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

Это сработает, если я удалю ссылку Персона на SpecialShirt. Как я могу иметь две ссылки на один столбец ("ShirtId")? Или есть лучший способ? Я не могу реально изменить структуру таблицы.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2010

Я нашел решение. Это некрасиво, но работает. Я добавил команду DynamicInsert () в PersonMap. Итак, карта сейчас:

public class TestPersonMap : ClassMap<TestPerson>
{
 public TestPersonMap()
 {
  Table("TestPerson");
  Id(x => x.PersonId).GeneratedBy.Native();
  Map(x => x.Name);
  References(x => x.Shirt).Column("ShirtId");
  References(x => x.SpecialShirt).Column("ShirtId"); 

  DynamicInsert();
 }
}

Затем я должен сохранить Рубашку и Персона по отдельности, чтобы каскад не работал.

Пока это работает. Честно говоря, я не знаю, что делает DynamicInsert. Я могу только найти устаревшую документацию и бесполезные ветки форума, когда исследую этот метод.

Я могу только предположить, что это потерпит неудачу в какой-то момент в будущем.

0 голосов
/ 12 ноября 2010

Как работают отношения?Обычно Person носит Shirt, а Shirt является либо Shirt, либо SpecialShirt.Поскольку SpecialShirt - это Shirt, человеку нужно иметь только ссылку на Shirt.NHibernate знает все о сопоставлениях таблицы на конкретный класс (что у вас есть).

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