NHibernate:JoinedSubclass,有许多

NHibernate:JoinedSubclass,有许多,nhibernate,nhibernate-mapping,polymorphism,has-many,joined-subclass,Nhibernate,Nhibernate Mapping,Polymorphism,Has Many,Joined Subclass,我使用FluentNHibernate(自动映射)进行映射,使用NHibernate 3.2进行数据访问,使用SchemaExport生成数据库 我有一个类Principal,它是User和Usergroup的基类。 Principal具有类型为CommonThing的属性CommonThing。 CommonThing有两套:ManagedUsers和ManagedUsergroups 现在为主体-表(确定)、用户-表(错误)、用户组-表(错误)生成一列CommonThingId 如何让Flu

我使用FluentNHibernate(自动映射)进行映射,使用NHibernate 3.2进行数据访问,使用SchemaExport生成数据库

我有一个类
Principal
,它是
User
Usergroup
的基类。
Principal
具有类型为
CommonThing
的属性
CommonThing
CommonThing
有两套:
ManagedUsers
ManagedUsergroups

现在为
主体
-表(确定)、
用户
-表(错误)、
用户组
-表(错误)生成一列
CommonThingId

如何让FluentNHibernate只生成
主体中的列而不生成子类表

编辑:类和映射 负责人:

public abstract class Principal : Entity
{
    ...
    public virtual CommonThing CommonThing
    {
        get
        {
            return _commonThing;
        }
        set
        {
            if (_commonThing == value)
                return;

            _commonThing = value;

            if (_commonThing == null)
                return;

            if (this is Usergroup)
                _commonThing.AddUsergroup(this as Usergroup);
            else if (this is User)
                _commonThing.AddUser(this as User);
        }
    }
    ...
}
用户:

用户组:

public partial class Usergroup : Principal
{
    ...
}
共同点:

public class CommonThing : Entity
{
    ...
    public virtual IEnumerable<User> ManagedUsers { get { return _managedUsers; } set { _managedUsers = (Iesi.Collections.Generic.ISet<User>)value; } }
    public virtual IEnumerable<Usergroup> ManagedUsergroups { get { return _managedUsergroups; } set { _managedUsergroups = (Iesi.Collections.Generic.ISet<Usergroup>)value; } }
    ...
}
主要映射:

public class PrincipalMapping : IAutoMappingOverride<Principal>
{
    public void Override(AutoMapping<Principal> mapping)
    {
        ...
        mapping.References(x => x.CommonThing)
            .LazyLoad()
            .Nullable()
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.None();
        ;
        mapping.JoinedSubClass<User>("Id");
        mapping.JoinedSubClass<Usergroup>("Id");
        ...
    }
}
公共类原则映射:IAutoMappingOverride
{
公共无效替代(自动映射)
{
...
mapping.References(x=>x.CommonThing)
.LazyLoad()
.Nullable()
.Access.CamelCaseField(前缀.下划线)
.Cascade.None();
;
映射。联合子类(“Id”);
映射。联合子类(“Id”);
...
}
}
常见映射:

public class CommonThingMapping : IAutoMappingOverride<CommonThing>
{
    public void Override(AutoMapping<CommonThing> mapping)
    {
        ...
        mapping.HasMany(x => x.ManagedUsers)
            .AsSet()
            .ExtraLazyLoad()
            ;
        mapping.HasMany(x => x.ManagedUsergroups)           
            .ExtraLazyLoad()
            .AsSet()            
            ;
        ...
    }
}
公共类CommonThingMapping:IAutoMappingOverride
{
公共无效替代(自动映射)
{
...
mapping.HasMany(x=>x.ManagedUsers)
1.资产()
.extrallazyload()
;
mapping.HasMany(x=>x.ManagedUsergroups)
.extrallazyload()
1.资产()
;
...
}
}
Lg
warappa

映射。HasMany(x=>x.ManagedUsers)
映射。HasMany(x=>x.managedUserGroup)
负责额外的
CommonThingId
-列

这应该做到:

mapping.HasMany<Principal>(x => x.ManagedUsers)
mapping.HasMany<Principal>(x => x.ManagedUsergroups)
编辑:@comment:对,我没见过这个

您可以为用户执行TPH(每个hirarchy的表)映射:在fluentnhibernate自动映射配置中
覆盖DiscriminateSubclasses()
{
返回true;
}

class SCConvention : ISubclassConvention
{
    Apply(...)
    {
        instance.DiscriminatorValue(instance.Type.Name);
    }
}

mapping.HasMany<Principal>(x => x.ManagedUsers).Where("discriminatorcolumn = 'User'")
mapping.HasMany<Principal>(x => x.ManagedUsergroups).Where("discriminatorcolumn = 'Usergroup'")
class-SCConvention:ISubclassConvention
{
应用(…)
{
DiscriminatorValue(instance.Type.Name);
}
}
mapping.HasMany(x=>x.ManagedUsers)。其中(“discriminatorcolumn='User')
mapping.HasMany(x=>x.ManagedUsergroups)。其中(“discriminatorcolumn='Usergroup')

因此,我终于找到了一种防止映射已映射的引用的方法:

public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
    ...
    public override bool ShouldMap(Member member)
    {
        ...
        var res = base.ShouldMap(member);
        if (res == true &&              
            typeof(IEnumerable).IsAssignableFrom(member.PropertyType) == false) // "References"
        {
            var originalDeclaringType = GetOriginalDeclaringType(member.MemberInfo);

            // is Reference declared in a base-type?
            if (!(originalDeclaringType == typeof(Entity) ||
                originalDeclaringType == typeof(Entity<int>)) &&
                originalDeclaringType != member.MemberInfo.ReflectedType)
                return false; // base-type already mapped it...
        }
        return res;
    }

    // Helper
    private Type GetOriginalDeclaringType(MemberInfo member)
    {
        List<Type> types = new List<Type>();

        Type type = member.ReflectedType;
        while (type != null)
        {
            types.Add(type);
            type = type.BaseType;
        }

        types.Reverse();

        foreach(var t in types)
        {
            var tmp = t.GetMember(member.Name, BindingFlags.Public |
                        BindingFlags.NonPublic |
                        BindingFlags.Instance |
                        BindingFlags.DeclaredOnly);
            if (tmp.Length != 0)
            {
                type = t;
                break;
            }
        }
        return type;
    }
    ...
}
公共类自动映射配置:默认自动映射配置
{
...
公共覆盖布尔ShouldMap(成员)
{
...
var res=基本的ShouldMap(成员);
如果(res==true&&
typeof(IEnumerable).IsAssignableFrom(member.PropertyType)==false)/“引用”
{
var originalDeclaringType=GetOriginalDeclaringType(member.MemberInfo);
//引用是否在基类型中声明?
if(!(originalDeclaringType==typeof(实体)||
originalDeclaringType==typeof(实体))&&
originalDeclaringType!=member.MemberInfo.ReflectedType)
return false;//基类型已映射它。。。
}
返回res;
}
//助手
私有类型GetOriginalDeclaringType(MemberInfo成员)
{
列表类型=新列表();
Type Type=member.ReflectedType;
while(type!=null)
{
类型。添加(类型);
type=type.BaseType;
}
类型。反向();
foreach(类型中的var t)
{
var tmp=t.GetMember(member.Name,BindingFlags.Public|
BindingFlags.NonPublic|
BindingFlags.Instance|
绑定标志(仅限声明);
如果(tmp.Length!=0)
{
类型=t;
打破
}
}
返回类型;
}
...
}
可能有一些情况会因此而导致副作用,但在我当前的非常非常复杂的项目中,它只是做了我想做的事情

Lg

瓦拉帕

请张贴代码。如果没有任何代码,我们无法告诉您如何修复“错误”。对不起,我现在添加了必要的信息。我想我已经尝试过了。它抛出了一个强制转换异常,即ManagedUsers不再只包含用户,而是包含用户组,尽管两者都是主体,但用户不是用户组。。。(但我同意你关于多态性的观点:))
public virtual CommonThing CommonThing
{
    get { return _commonThing; }
    set
    {
        if (_commonThing == value)
            return;

        _commonThing = value;

        if (_commonThing != null)
            AddThisToCommonThing(_commonThing);
    }
}

protected abstract void AddThisToCommonThing(CommonThing common);
class SCConvention : ISubclassConvention
{
    Apply(...)
    {
        instance.DiscriminatorValue(instance.Type.Name);
    }
}

mapping.HasMany<Principal>(x => x.ManagedUsers).Where("discriminatorcolumn = 'User'")
mapping.HasMany<Principal>(x => x.ManagedUsergroups).Where("discriminatorcolumn = 'Usergroup'")
public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
    ...
    public override bool ShouldMap(Member member)
    {
        ...
        var res = base.ShouldMap(member);
        if (res == true &&              
            typeof(IEnumerable).IsAssignableFrom(member.PropertyType) == false) // "References"
        {
            var originalDeclaringType = GetOriginalDeclaringType(member.MemberInfo);

            // is Reference declared in a base-type?
            if (!(originalDeclaringType == typeof(Entity) ||
                originalDeclaringType == typeof(Entity<int>)) &&
                originalDeclaringType != member.MemberInfo.ReflectedType)
                return false; // base-type already mapped it...
        }
        return res;
    }

    // Helper
    private Type GetOriginalDeclaringType(MemberInfo member)
    {
        List<Type> types = new List<Type>();

        Type type = member.ReflectedType;
        while (type != null)
        {
            types.Add(type);
            type = type.BaseType;
        }

        types.Reverse();

        foreach(var t in types)
        {
            var tmp = t.GetMember(member.Name, BindingFlags.Public |
                        BindingFlags.NonPublic |
                        BindingFlags.Instance |
                        BindingFlags.DeclaredOnly);
            if (tmp.Length != 0)
            {
                type = t;
                break;
            }
        }
        return type;
    }
    ...
}