I have a database structure where one table extends another table开发者_StackOverflow中文版, and then a third table has a foreign key that is valid in the first two tables.
For example:
TABLE Person
PersonId int
Name varchar
ShirtId int
TABLE Shirt
ShirtId int
Color string
TABLE SpecialShirt
ShirtId int
Sleeves int
The classes look like this:
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; }
}
And the mappings look like this:
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");
}
}
I then try saving a new instance of Person and Shirt like this:
var shirt1 = new TestShirt() {Color = "Red"};
var person1 = new TestPerson() {Name = "Fred Person", Shirt = shirt1};
shirt1.AddPerson(person1);
session.Save(shirt1);
session.Save(person1);
This code gets the following error:
System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
It works if I remove the reference from Person to SpecialShirt. Howe can I have two references on the same column ("ShirtId")? Or is there a better way? I can't really change the table structure.
How does the relationship work?
Usually, a Person
wears a Shirt
, and a Shirt
is either a Shirt
or a SpecialShirt
. Because a SpecialShirt
is a Shirt
, a Person need only have a reference to a Shirt
. NHibernate knows all about table-per-concrete-class mappings (which is what you have).
I found a solution. It's ugly, but it's working. I added the command DynamicInsert() into the PersonMap. So the map is now:
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();
}
}
I then have to save the Shirt and Person separately, so the cascade is not really working.
This is working so far. I honestly don't know what DynamicInsert does. I can only find out-of-date documentation and unhelpful forum threads when researching this method.
I can only assume this will be fail at some point in the future.
精彩评论