【问题标题】:Fluent NHibernate many-to-many using non-PK columnFluent NHibernate 多对多使用非 PK 列
【发布时间】:2012-08-17 22:20:42
【问题描述】:

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

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

由于遗留原因,用户和组中的 AdGuid 字段(唯一标识符)不是主键。但是,我想使用 MessageUserGroups 中的 UserId 和 GroupId 字段通过其 AdGuid 字段将消息与用户和组相关联。

此外,我希望在 User 上有一个 PostedMessages 属性,它将 Message.AuthorId 与 User.AdGuid 相关联,并在 User 和 Group 上拥有 Messages 属性,通过 MessageUserGroups 与消息相关。

我该如何向 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

该联接无效,因为它正在尝试将 uniqueidentifer 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 需要是唯一标识符。

在这两个之后,我得到一个 SqlException: Operand type clash: uniqueidentifier is incompatible with bigint,这是意料之中的。

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

【问题讨论】:

    标签: sql-server nhibernate fluent-nhibernate


    【解决方案1】:

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

    【讨论】:

    • 设置 ParentKeyColumn 和 ChildKeyColumn 并仅在关系的 Message 端定义映射就可以了。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多