NHibernate - 使用多对多链接的继承映射返回到同一个表

时间:2013-04-28 14:10:26

标签: nhibernate nhibernate-mapping

在NHibernate中,我正在使用Table-per-Class Hierarchy Inheritance映射。我的表看起来像这样:

Table relationship

Items表具有继承映射,有3个C#类(实体),它们是'UserProfiles','Destinations'和'Groups',ItemType列是鉴别器。 ItemMembers表将Items表链接回自身(通过多对多),以便用户可以属于多个目标或组,而目标/组可以有许多用户等。

我使用类似的方式映射它:

public class ItemMap : ClassMapping<Item>
{
    public ItemMap()
    {
        Table("Items");
        Id(...snip...

        Discriminator(x => { x.Column("ItemType"); x.Force(true); });

        ...other props (snip)...

和,其中一个实体:

public class UserProfileMap : SubclassMapping<UserProfile>
{
    public UserProfileMap()
    {
        DiscriminatorValue("UserProfile");

        .... other props (snip)...

目标和组的映射类似,它们的所有类都扩展了Item类:

public class UserProfile : Item { }
public class Destination : Item { }
public class Group : Item { }

到目前为止,这似乎很有效。我的问题是我想将UserProfiles链接到Destinations,反之亦然。所以我创建了一个UserDestination实体并映射它:

public class UserDestination
{
    public virtual UserProfile Profile { get; set; }
    public virtual Destination Destination { get; set; }
}

public class UserDestinationMap : ClassMapping<UserDestination>
{
    public UserDestinationMap()
    {
        Table("ItemMembers");

        Id(... snip...

        ManyToOne(x => x.Profile, x =>
        {
            x.Column("ChildItemId");
            x.NotNullable(true);
        });

        ManyToOne(x => x.Destination, x =>
        {
            x.Column("ParentItemId");
            x.NotNullable(true);
        });
    }
}

public class UserProfile : Item
{
    .... other props (snip)....
    public virtual ISet<UserDestination> FollowedDestinations { get; set; }
}

...麻烦的是,每当我尝试为用户检索目标时,我也会得到组(因为同一个表用于多对多链接),我收到以下错误:

var usersDestinations = userProfile.FollowedDestinations
    .Select(fd => fd.Destination)
    .ToList();

Unable to cast object of type 'MyApp.Group' to type 'MyApp.Destination'.

我可以通过在UserProfile实体上映射UserDestinations集合时包含WHERE子句来解决这个问题:

Set(x => x.FollowedDestinations, x =>
{
    x.Inverse(true);
    x.Cascade(Cascade.All | Cascade.DeleteOrphans);
    x.Lazy(CollectionLazy.Extra);
    x.Key(k => { k.Column("ChildItemId"); });
    x.Where("(SELECT COUNT(*) FROM Items xitems WHERE xitems.Id = ParentItemId AND xitems.ItemType = 'Destination') > 0");
}, x => x.OneToMany());

但这似乎有点像黑客,我不知道是否会有未来的潜在问题。那么有更好的方法吗?

0 个答案:

没有答案