2011-06-11 10 views
0

마스터 계정과 하위 계정을 저장하는 계정 테이블이 있습니다. 마스터 계정은 기본적으로 하위 계정과 동일하지만 관련 회사가있을 수 있습니다. 계정은 추상 클래스이며 MasterAccount와 SubAccount는 둘 다 파생됩니다.FluentNHibernate 하위 클래스 및 계층 적 데이터

MasterAccount는 ParentAccountId가 null 인 계정 항목입니다. 계정 레코드에 ParentAccountId가 있으면 SubAccount이고 ParentAccountId는 MasterAccount의 AccountId 필드를 참조합니다.

나는 그들을위한 FluentNhibernate 매핑을 얻으려고합니다.

클래스

내가 가진 다음

public class Account : EntityBase 
    { 
     public Account() { } 

     public virtual string AccountNumber { get; set; } 

     public virtual string AccountName { get; set; } 

     public virtual string ContactRole { get; set; } 

     public virtual bool EmailBillDataFile { get; set; } 

     public virtual bool EmailBill { get; set; } 

     public virtual bool PostBill { get; set; } 

     public virtual BillingMethod BillingMethod { get; set; } 

     public virtual BillingAddressType BillingAddressType { get; set; } 

     public virtual Contact Contact { get; set; } 

     public virtual bool IsInvoiceRoot { get; set; } 

     public virtual string Password { get; set; } 

     public virtual bool HasRequestedInvoicing { get; set; } 

     public virtual bool IsInternational { get; set; } 

     public virtual decimal AmountPaid { get; set; } 

     public virtual decimal PreviousBill { get; set; } 

     public virtual void MakePayment(decimal amount) 
     { 
      MakePayment(amount, null); 
     } 

     public virtual void MakePayment(decimal amount, string invoiceNumber) 
     { 
      AmountPaid += amount; 

      if (string.IsNullOrEmpty(invoiceNumber)) 
       LogActivity(string.Format("Made payment of {0:c}", amount)); 
      else { 
       LogActivity(string.Format("Made payment of {0:c} on Invoice '{1}'", amount, invoiceNumber)); 
      } 
     } 

     public virtual Invoice CreateInvoice() 
     { 
      Invoice invoice; 
      invoice = IsInternational ? new NoGstInvoice() : new Invoice(); 

      // Can update invoice properties that rely on account data here. 


      return invoice; 
     } 

     #region Business Rules 

     public override IEnumerable<RuleViolation> GetRuleViolations() 
     { 
      if (string.IsNullOrEmpty(AccountName)) 
       yield return new RuleViolation("Account Name required", "AccountName"); 

      if (string.IsNullOrEmpty(AccountNumber)) 
       yield return new RuleViolation("Acocunt Number required", "AccountNumber"); 

      if (string.IsNullOrEmpty(Password)) 
       yield return new RuleViolation("Password required", "Password"); 

      yield break; 
     } 

     #endregion 

    } 

    public class MasterAccount : Account 
    { 
     private Company _company; 
     private IList<SubAccount> _subAccounts; 

     public MasterAccount() : this(null) { } 

     public MasterAccount(Company company) 
     { 
      _company = company; 
      _subAccounts = new List<SubAccount>(); 
     } 

     public virtual Company Company 
     { 
      get { return _company; } 
     } 

     public virtual IEnumerable<SubAccount> SubAccounts 
     { 
      get { return _subAccounts; } 
     } 

     public virtual SubAccount CreateSubAccount(string accountNumber, string accountName) 
     { 
      var subAccount = new SubAccount(this) 
           { 
            AccountName = accountName, 
            AccountNumber = accountNumber, 
            Contact = this.Contact, 
            ContactRole = this.ContactRole, 
            PreviousBill = 0, 
            AmountPaid = 0, 
            BillingAddressType = this.BillingAddressType, 
            BillingMethod = this.BillingMethod, 
            IsInternational = this.IsInternational, 
            IsInvoiceRoot = false, 
            EmailBill = this.EmailBill, 
            EmailBillDataFile = this.EmailBillDataFile, 
            Password = this.Password, 
            PostBill = this.PostBill          
           }; 

      return subAccount; 
     }  
    } 

public class SubAccount : Account 
    { 
     private MasterAccount _masterAccount; 

     public SubAccount() { } 

     public SubAccount(MasterAccount master) 
     { 
      _masterAccount = master; 
     } 

     public virtual MasterAccount MasterAccount 
     { 
      get { return _masterAccount; } 
     }   
    } 

매핑과 같이이다 : 그러나

public class AccountMap : ClassMap<Account> 
{ 
    public AccountMap() 
    { 
     Table("Account"); 
     Id(x => x.Id).Column("AccountId").GeneratedBy.Identity(); 
     Map(x => x.AccountName).Length(50).Not.Nullable(); 
     Map(x => x.AccountNumber).Length(10).Not.Nullable(); 
     Map(x => x.ContactRole).Length(50); 
     Map(x => x.BillingMethod).Not.Nullable(); 
     Map(x => x.EmailBill).Not.Nullable(); 
     Map(x => x.PostBill).Not.Nullable(); 
     Map(x => x.EmailBillDataFile).Not.Nullable(); 
     Map(x => x.BillingAddressType).Not.Nullable(); 
     Map(x => x.IsInvoiceRoot).Not.Nullable(); 
     Map(x => x.HasRequestedInvoicing).Not.Nullable(); 
     Map(x => x.IsInternational).Not.Nullable(); 
     Map(x => x.PreviousBill).Not.Nullable(); 
     Map(x => x.AmountPaid).Not.Nullable(); 
     Map(x => x.Password).Length(20).Not.Nullable(); 

     References(x => x.Contact).Column("ContactId").Not.Nullable(); 

     DiscriminateSubClassesOnColumn("ParentAccountId"); 
    } 
} 

public class MasterAccountMap : SubclassMap<MasterAccount> 
{ 
    public MasterAccountMap() 
    {    
     References(x => x.Company).Column("CompanyId"); 
     HasMany(x => x.SubAccounts).KeyColumn("ParentAccountId").Inverse().Cascade.All(); 
    } 
} 

public class SubAccountMap : SubclassMap<SubAccount> 
{ 
    public SubAccountMap() 
    { 
     References(x => x.MasterAccount).Column("ParentAccountId").Not.Nullable(); 
    } 
} 

나는 다음과 같은 테스트를 실행할 때, :

[Test] 
public void Can_add_subAccount_to_database() 
{ 
    var master = Session.Get<MasterAccount>(1); 
    var subAccount = master.CreateSubAccount("TST123", "Test Account"); 

    Session.Save(subAccount); 
    Session.Flush(); 
    Session.Clear(); 

    var fromDb = Session.Get<SubAccount>(subAccount.Id); 
    Assert.AreNotSame(subAccount, fromDb); 
} 

을 나는 예외가 Session.Save (subAccount); 선.

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection. 
Parameter name: index 

SubAccountMap의 참조 매핑을 주석 처리하면 예외가 적용되지 않습니다.
이 관계를 올바르게 매핑하는 데 도움이되는 정보가 있으면 알려주세요.

답변

0

제가

DiscriminateSubClassesOnColumn("").Formula("case when parentaccountid is null then '0' else '1' end"); 

DiscriminateSubClassesOnColumn

를 수식 방법을 사용하고

DiscriminatorValue("0"); // In MasterAccountMap 

DiscriminatorValue("1"); // in SubAccountMap 

http://wiki.fluentnhibernate.org/Fluent_mapping

참조 서브 클래스들 각각에 다음 사용에 필요한 같다
관련 문제