流利的NHibernate使用非PK列多对多

时间:2012-08-17 22:20:42

标签: sql-server nhibernate fluent-nhibernate

我需要在其中两个中使用非PK列关联一些表。表和FK的设置如下:

enter image description here

因此可以通过MessageUserGroups表将消息分配给许多用户和组。此外,可以通过UserGroups表将用户分配给许多组。

用户和组中的AdGuid字段(uniqueidentifier)不是传统原因的主键。但是,我想使用MessageUserGroups中的UserId和GroupId字段通过其AdGuid字段将消息与用户和组相关联。

此外,我想在User上有一个PostedMessages属性,它将Message.AuthorId与User.AdGuid相关联,并且在User和Group上有Messages属性,它们通过MessageUserGroups与Messages相关。

我如何向Fluent NHibernate解释这个?

目前映射看起来像:

public MessageMap()
{
    Id(m => m.Id);
    References(m => m.Author).Nullable().ForeignKey("FK_Messages_Author").Column("AuthorId").Fetch.Join().PropertyRef(u => u.AdGuid);

    HasManyToMany<users.user>(m => m.Users)
        .Cascade.All()
        .ParentKeyColumn("MessageId")
        .ChildKeyColumn("UserId")
        .Table("MessageUserGroups")
        .FetchType.Join();

    HasManyToMany<users.group>(m => m.Groups)
        .Cascade.All()
        .ParentKeyColumn("MessageId")
        .ChildKeyColumn("GroupId")
        .Table("MessageUserGroups")
        .FetchType.Join();
}
public UserMap()
{
    Id(u => u.Id);
    Map(u => u.AdGuid);

    HasManyToMany<staff.Message>(u => u.Messages)
        .Cascade.All()
        .ParentKeyColumn("AdGuid")
        .ChildKeyColumn("UserId")
        .Inverse()
        .LazyLoad()
        .Table("MessageUserGroup")

    HasMany<staff.Message>(u => u.PostedMessages)
        .Cascade.All()
        .KeyColumn("AuthorId")
        .Inverse()
        .LazyLoad()
        .Table("Messages")

    HasManyToMany<Group>(u => u.Groups)
        .Cascade.All()
        .Not.LazyLoad()
        .Cascade.All()
        .ParentKeyColumn("UserID")
        .ChildKeyColumn("GroupID")
        .Table("UserGroups")
}
public GroupMap()
{
    Id(g => g.Id);
    Map(g => g.AdGuid);

    HasManyToMany<staff.Message>(g => g.Messages)
        .Cascade.All()
        .ParentKeyColumn("AdGuid")
        .ChildKeyColumn("GroupId")
        .Inverse()
        .LazyLoad()
        .Table("MessageUserGroup")

    HasManyToMany<User>(g => g.Users)
        .Inverse()
        .Cascade.All()
        .ParentKeyColumn("GroupId")
        .ChildKeyColumn("UserId")
        .Table("UserGroups")
}

我知道,有点冗长。我可以使用NH成功查询消息。但是,当延迟加载User或Group的Messages属性时,NH会生成此SQL(为简洁起见,删除了额外的属性):

SELECT users0_.MessageId as MessageId1_, users0_.UserId as UserId1_, user1_.Id
as id38_0_, user1_.AdGuid as guid38_0_ FROM MessageUserGroups users0_
LEFT OUTER JOIN Users user1_ on users0_.UserId=user1_.Id WHERE users0_.MessageId=@p0

该连接无效,因为它正在尝试将唯一标识MessageUserGroups.UserId与bigint User.Id进行比较。

同样,当延迟加载User.PostedMessages时,会生成此SQL(再次,缩写):

SELECT postedmess0_.AuthorId as AuthorId1_, postedmess0_.Id as Id1_, postedmess0_.Id as Id43_0_, postedmess0_.AuthorId as AuthorId43_0_
FROM Staff.Messages postedmess0_
WHERE postedmess0_.AuthorId=@p0

并且@p0设置为89,这是我正在测试的用户的ID,但AuthorId需要是唯一标识符。

在我完成这两项工作之后,我得到了SqlExceptionOperand type clash: uniqueidentifier is incompatible with bigint

看起来像(流畅)NHibernate总是想加入PK,即使文档建议指定ParentKeyColumn和ChildKeyColumn应该允许我指定我喜欢的任何列。这真的有可能吗?我误读了吗?

1 个答案:

答案 0 :(得分:1)

ParentKeyColumn和ChildKeyColumn指定链接表中的列名,而不是连接的实体表的列。您需要在hasmanytomany上PropertyRefChildPropertyRef指定要加入的属性