微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FluentNHibernate子类和层次结构数据

如何解决FluentNHibernate子类和层次结构数据

| 我有一个帐户表,用于存储主帐户和子帐户。主帐户与子帐户基本相同,区别在于主帐户可以具有关联公司。帐户是一个抽象类,Masteraccount和SubAccount都从该类派生。 Masteraccount是任何具有空ParentAccountId的帐户条目。如果帐户记录具有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中的References映射,则不会出现异常。 任何帮助正确映射此关系表示赞赏。     

解决方法

        似乎我需要在DiscriminateSubClassesOnColumn上使用Formula方法
DiscriminateSubClassesOnColumn(\"\").Formula(\"case when parentaccountid is null then \'0\' else \'1\' end\");
然后在每个子类中使用以下内容
DiscriminatorValue(\"0\");  // In MasterAccountMap

DiscriminatorValue(\"1\"); // in SubAccountMap
参见http://wiki.fluentnhibernate.org/Fluent_mapping     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。