NHibernate:具有多个继承字段的map类

时间:2014-03-17 12:01:29

标签: c# nhibernate nhibernate-mapping

我的项目中有以下实体,我想使用NHibernate属性进行映射:

public interface IContent
{
    int Id { get; set; }
    string Name { get; set; }
}

public interface IUser
{
    int Id { get; set; }
}

[Class]
public class Book : IContent
{
    [Id(...), Column(...), Generator(...)]
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
}

[Class]
public class Collection : IContent
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

[Class]
public class Reader : IUser
{
    [Id(...), Column(...), Generator(...)]
    public virtual int Id { get; set; }

    [Property]
    public virtual string Email { get; set; }
}

[Class]
public class ReaderGroup : IUser
{
    [Id(...), Column(...), Generator(...)]
    public virtual int Id { get; set; }

    [ManyToMany(...)]
    public virtual ISet<Reader> Readers { get; set; }
}

现在我想实现统一的访问控制机制:

public class AccessPermission
{
    [Id(...), Column(...), Generator(...)]
    public virtual int Id { get; set; }

    public virtual IContent Object { get; set; }

    public virtual IUser Subject { get; set; }
}

诀窍是两个字段接受不同类型的值:ObjectSubject。我之前使用过DiscriminatorSubclass属性,但之后只有一个字段包含继承类型,而不是两个或更多。

有没有一种聪明的方法来实现这种情况?

1 个答案:

答案 0 :(得分:1)

NHibernate并不能很好地使用接口,因为它的工作方式是通过继承实体来创建类的代理(因此你必须将所有字段定义为virtual)。

我要做的不是你的接口,而是使用抽象类,例如

public abstract class User
{
    public virtual int Id { get; protected set; }
    public virtual IEnumerable<AccessPermission> AccessPermissions { get; protected set; }
}

然后(使用Fluent NHibernate

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        this.Id(x => x.Id);
        this.HasMany(x => x.AccessPermissions);
        this.DiscriminateSubClassesOnColumn("Type");
    }
}

以及您的子类:

public class ReaderMap : SubClassMap<Reader>
{
    public ReaderMap()
    {
        this.DiscriminatorValue("Reader");
        this.Map(x => x.Email);
    }
}

代表AccessPermission

public class AccessPermissionMap : ClassMap<AccessPermission>
{
    public AccessPermissionMap()
    {
        this.Id(x => x.Id);
        this.References(x => x.Object);
        this.References(x => x.Subject);
    }
}

然后NH会为您完成所有艰苦的工作,并根据AccessPermission

中的FK ID确定要实例化的子类