TL; DR :我正在尝试在多对多表上添加多对多Order
列的多对多映射。 HBM效果很好。无法使FluentNHibernate映射生效。
我有以下两个类,我试图用多对多关系映射:
public class User
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
private IDictionary<int, Profile> profilesMap;
public virtual IEnumerable<Profile> Profiles { get { return this.profilesMap.Select(kvp => kvp.Value); } }
public User()
{
this.profilesMap = new SortedDictionary<int, Profile>();
}
public virtual void Add(Profile x)
{
profilesMap.Add(x);
}
}
public class Profile
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
profilesMap
的关键是个人资料订单。因此,HBM映射如下:
<class name="User" table="User">
<id name="Id" column="Id" type="integer">
<generator class="native" />
</id>
<property name="Name" type="string" column="Name" />
<map name="profilesMap" access="field.camelcase" table="User_Profile">
<key column="User_Id" />
<index column="`Order`" type="integer" />
<many-to-many class="Profile" column="Profile_Id" />
</map>
</class>
<class name="Profile" table="Profile">
<id name="Id" column="Id" type="integer">
<generator class="native" />
</id>
<property name="Name" type="string" column="Name" />
</class>
这非常有效,可以创建正确的多对多表格:
create table User_Profile (
User_Id INT not null,
Profile_Id INT not null,
"Order" INT not null,
primary key (User_Id, "Order"),
constraint FK6BDEDC07D1EDE651 foreign key (Profile_Id) references Profile,
constraint FK6BDEDC07650CB01 foreign key (User_Id) references User
)
但是,我并不特别喜欢使用HBM,因为它不是真正重构的。因此,我正在尝试将其转换为FluentNHibernate。这是我尝试用户的多对多映射:
public class UserMap : ClassMap<User>
{
public UserMap()
{
this.Id();
this.Map(o => o.Name);
var mapMember = Reveal.Member<User, IEnumerable<KeyValuePair<int, Profile>>>("profilesMap");
this.HasManyToMany<KeyValuePair<int, Profile>>(mapMember)
.Access.CamelCaseField()
.AsMap<int>("`Order`")
.Table("User_Profile");
}
}
我希望这可以工作,但是在尝试构建会话工厂时它会爆炸:
表User_Profile中的关联引用未映射的类:System.Collections.Generic.KeyValuePair`2 [[System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089],[ConsoleApplication9。 Profile,ConsoleApplication9,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]
我做了很多关于如何让AsMap
工作的研究,所以我把它改成了以下内容:
this.HasManyToMany<KeyValuePair<int, Profile>>(mapMember)
.Access.CamelCaseField().AsMap<int>("`Order`")
.Element("Profile_id", ep => ep.Type<int>()) // Added.
.Table("User_Profile");
但是,这会产生一个不正确的表格 not ,包括来自Profile_id
的外键(或非空约束):
create table User_Profile (
User_id INT not null,
Profile_id INT,
"Order" INT not null,
primary key (User_id, "Order"),
constraint FK6BDEDC07650CB01 foreign key (User_id) references "User")
此外,在尝试向用户添加个人资料时,它也会爆炸:
var a = new User() { Name = "A" };
var b = new Profile() { Name = "B" };
a.Add(b);
session.Save(b);
session.Save(a);
session.Flush(); // Error: Unable to cast object of type 'ConsoleApplication9.Profile' to type 'System.IConvertible'.
所以 - 我已经把头发拉了几个小时试图确定如何正确地映射这种关系与FNH,但我似乎无法得到它。简单的多对多关系看起来很简单,但在尝试添加索引列时,它似乎不起作用。如果有人愿意帮助我解决这个问题,我将不胜感激。
答案 0 :(得分:2)
您是否看到过类似问题的答案?
How to map IDictionary<string, Entity> in Fluent NHibernate
我看到的一个问题是你在很多人中使用了Element。这可能就是为什么你没有得到profile_id的任何外键设置。另外,如果可能的话,我会尝试为profilesMap添加一个公共访问器。
为了符合您的情况,我会按照以下方式进行映射:
HasManyToMany<Profile>(ProfilesMap) //Assuming the addition of a public get accessor
.Access.CamelCaseField()
.ParentKeyColumn("User_Id")
.ChildKeyColumn("Profile_Id")
.Table("User_Profile")
.AsMap<int>("Id");
如果您无法添加访问者,可以尝试使用
HasManyToMany<Profile>(Reveal.Member<User, object>("profilesMap"))
.Table("User_Profile")
.ParentKeyColumn("User_id")
.ChildKeyColumn("Profile_id")
.AsMap<int>("`Order`");