NHibernate:JoinedSubclass,有许多
我使用FluentNHibernate(自动映射)进行映射,使用NHibernate 3.2进行数据访问,使用SchemaExport生成数据库 我有一个类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
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;
}
...
}