0

我使用FluentNHibernate(Automapping)進行映射,NHibernate 3.2用於數據訪問,SchemaExport用於生成我的數據庫。NHibernate:JoinedSubclass,HasMany

我有一個類Principal這是UserUsergroup的基類。 Principal有一個屬性CommonThing類型CommonThingCommonThing有2組:ManagedUsersManagedUsergroups

現在爲Principals -table(OK),Users -table(WRONG),Usergroups -table(WRONG)生成了一列CommonThingId

如何獲得FluentNHibernate到只生成Principals -table中的列而不是子類別表?

編輯:類&映射 校長:

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 User : Principal 
{ 
    ... 
} 

用戶組:

public partial class Usergroup : Principal 
{ 
    ... 
} 

CommonThing:

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 ReferenceConvention : IReferenceConvention 
{ 
    public void Apply(IManyToOneInstance instance) 
    { 
     var keyName = string.Format(CultureInfo.InvariantCulture, "FK_MtO_{0}_in_{1}_{2}", 
           instance.Property.PropertyType.Name, 
           instance.EntityType.Name, 
           instance.Name); 
     instance.ForeignKey(keyName); 

     instance.LazyLoad();    

     instance.Cascade.SaveUpdate(); 

     instance.Column(instance.Property.PropertyType.Name + "Id"); 

     instance.Access.CamelCaseField(CamelCasePrefix.Underscore); 
    } 
} 

public class ForeignKeyConvention : FluentNHibernate.Conventions.ForeignKeyConvention 
{ 
    protected override string GetKeyName(Member property, Type type) 
    { 
     if (property == null) 
      return type.Name + "Id"; 

     return property.Name + "Id"; 
    } 
} 

public class HasManyConvention : IHasManyConvention 
{ 
    public void Apply(IOneToManyCollectionInstance instance) 
    { 
     var keyName = string.Format(CultureInfo.InvariantCulture, "FK_OtM_{0}_{1}2{2}", 
           instance.Member.ReflectedType.Name, 
           instance.Member.Name, 
           instance.EntityType.Name); 

     instance.Key.ForeignKey(keyName); 

     if(instance.Key.Columns.Count() != 0) 
      instance.Inverse(); 
     instance.Cascade.SaveUpdate(); 

     instance.Cache.ReadWrite(); 
     instance.Cache.IncludeAll(); 

     instance.Access.CamelCaseField(CamelCasePrefix.Underscore); 
    } 
} 

public class JoinedSubclassConvention : IJoinedSubclassConvention 
{ 
    public void Apply(IJoinedSubclassInstance instance) 
    { 
     instance.Table("" + Inflector.Net.Inflector.Pluralize(instance.Type.Name)); 
     instance.Key.Column("Id"); 

     instance.DynamicInsert(); 
     instance.DynamicUpdate(); 

     instance.LazyLoad();    
    } 
} 

主體映射:

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"); 
     ... 
    } 
} 

CommonThing映射:

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()    
      ; 
     ... 
    } 
} 

了Lg
warappa

+2

請張貼代碼。我們無法告訴您如何解決「錯誤」而無需任何代碼。 –

+0

對不起,我現在添加了必要的信息。 –

回答

0

所以,我終於找到了一種方法,以防止映射參考其已經映射:

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; 
    } 
    ... 
} 

可能是由於這種情況導致副作用,但在我目前的非常非常複雜的項目它只是做了我想要的。

了Lg
warappa

0

mapping.HasMany(x => x.ManagedUsers)mapping.HasMany(x => x.ManagedUsergroups)負責額外的CommonThingId列。

這應該做:

mapping.HasMany<Principal>(x => x.ManagedUsers) 
mapping.HasMany<Principal>(x => x.ManagedUsergroups) 

和我不能抗拒。我認爲多態性會更好,這裏

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); 

編輯:@comment:對的,我還沒有看到這個

,你可以做一個用戶TPH(表每hirarchy)映射:在fluentnhibernate自動映射配置override DiscriminateSubclasses() { return 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'") 
+0

我想我已經試過了。它拋出了一個轉換異常,即ManagedUsers不僅僅包含用戶,而是用戶組,雖然它們都是委託人,但用戶不是用戶組...(但我同意你關於多態性的觀點:)) –