意外的NHibernate获取行为

意外的NHibernate获取行为,nhibernate,Nhibernate,我有一个带有5个域对象的棕色字段应用程序:CreditMemo、CreditMemoDetail、SalesInvoice、ReceivablesRecord、TransactionType。CreditMemo是一个——许多都有CreditMemo的细节。销售发票也是多对一的。SalesInvoice是带有ReceivablesRecord的一对多记录,它是带有TransactionType的多对一记录(下面是xml映射)。所有关系都不依赖于其直接父/子关系之外的任何值 当我执行Get(id)

我有一个带有5个域对象的棕色字段应用程序:CreditMemo、CreditMemoDetail、SalesInvoice、ReceivablesRecord、TransactionType。CreditMemo是一个——许多都有CreditMemo的细节。销售发票也是多对一的。SalesInvoice是带有ReceivablesRecord的一对多记录,它是带有TransactionType的多对一记录(下面是xml映射)。所有关系都不依赖于其直接父/子关系之外的任何值


当我执行Get(id)时,我正确地返回了整个结构:CreditMemo中的列正确填写,ISet正确,整个SalesInvoice/ReceivablesRecord/TransactionType层次结构完全填充。执行Get(invoiceNumber)时,SalesInvoice对象已正确填充,但ISet为空。使用NHProfiler,执行完全相同的查询,包括参数。我已经花了好几个小时来讨论这个问题,但还没有找到任何有意义的东西

我知道我可以用蛮力来处理事情,但事实上,当我从CreditMemo开始,而不是从SalesInvoice开始时,这种关系会自动运作,这让我抓狂。有什么想法吗

对象和映射:

public class CreditMemo
{
    public virtual int CreditMemoId { get; set; }
    public virtual string CreditMemoNumber { get; set; }
    public virtual DateTime CreditDate { get; set; }
    public virtual string InvoiceNumber { get; set; }
    public virtual string ReturnToStock { get; set; }
    public virtual string Posted { get; set; }
    public virtual string Notes { get; set; }
    public virtual Iesi.Collections.Generic.ISet<CreditMemoDetail> Details { get; set; }
    public virtual SalesInvoice InvoiceInfo { get; set; }
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" schema="aladdin" namespace="Receivables.Models">
  <class name="Receivables.Models.CreditMemo, Receivables" lazy="false" table="credit_memo">
    <id name="CreditMemoId" column="credit_memo_id">
      <generator class="identity" />
    </id>
    <property name="InvoiceNumber" column="invoice_no" />
    <property name="CreditMemoNumber" column="credit_memo_no" />
    <property name="CreditDate" column="credit_date" type="DateTime" />
    <property name="ReturnToStock" column="return_to_stock" />
    <property name="Posted" column="posted" />
    <property name="Notes" column="notes" />
    <many-to-one name="InvoiceInfo" class="SalesInvoice" column="invoice_no" update="false" insert="false" />
    <set name="Details" cascade="delete">
      <key column="credit_memo_id" />
      <one-to-many class="CreditMemoDetail"/>
    </set>
  </class>
</hibernate-mapping>

public class CreditMemoDetail
{
    public virtual int CreditMemoDetailId { get; set; }
    public virtual int CreditMemoId { get; set; }
    public virtual string CreditType { get; set; }
    public virtual decimal Amount { get; set; }
    public virtual string AffectCommission { get; set; }
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" schema="aladdin" namespace="Receivables.Models">
  <class name="Receivables.Models.CreditMemoDetail, Receivables" lazy="false" table="cr_memo_detail">
    <id name="CreditMemoDetailId" column="crmemodetailid">
      <generator class="identity" />
    </id>
    <property name="CreditMemoId" column="credit_memo_id" />
    <property name="CreditType" column="credit_type" />
    <property name="Amount" column="amount" />
    <property name="AffectCommission" column="affect_commission" />
  </class>
</hibernate-mapping>

public class SalesInvoice
{
    public virtual string InvoiceNumber { get; set; }
    public virtual string Customer { get; set; }
    public virtual DateTime InvoiceDate { get; set; }
    public virtual string SalesPerson { get; set; }
    public virtual string ClassOfSale { get; set; }
    public virtual Iesi.Collections.Generic.ISet<ReceivablesRecord> Transactions { get; set; }
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" schema="aladdin" namespace="Receivables.Models">
  <class name="Receivables.Models.SalesInvoice, Receivables" lazy="false" table="invoice">
    <id name="InvoiceNumber" column="invoice_no">
      <generator class="assigned" />
    </id>
    <property name="Customer" column="customer" />
    <property name="InvoiceDate" column="invoice_date" type="DateTime" />
    <property name="SalesPerson" column="salesman" />
    <property name="ClassOfSale" column="class" />
    <set name="Transactions">
      <key column="invoice_no" />
      <one-to-many class="ReceivablesRecord"/>
    </set>
  </class>
</hibernate-mapping>

public class ReceivablesRecord
{
    public virtual string InvoiceNumber { get; set; }
    public virtual DateTime AccrecDate { get; set; }
    public virtual string TxType { get; set; }
    public virtual decimal Amount { get; set; }
    public virtual string Note { get; set; }
    public virtual TransactionType TypeInfo { get; set; }
    public override bool Equals(object obj)
    {
        bool result = false;
        try
        {
            ReceivablesRecord input = (ReceivablesRecord)obj;
            if (InvoiceNumber == input.InvoiceNumber && AccrecDate == input.AccrecDate && TxType == input.TxType)
            {
                result = true;
            }
        }
        catch (Exception ex)
        {
        }

        return result;
    }

    public override int GetHashCode()
    {
        return string.Format("{0}{1}{2}", InvoiceNumber, AccrecDate, TxType).GetHashCode();
    }
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" schema="aladdin" namespace="Receivables.Models">
  <class name="Receivables.Models.ReceivablesRecord, Receivables" lazy="false" table="accrec">
    <composite-id>
      <key-property name="InvoiceNumber" column="invoice_no" />
      <key-property name="AccrecDate" column="accrec_date" type="DateTime" />
      <key-property name="TxType" column="tx_type" />
    </composite-id>
    <property name="Amount" column="amount" />
    <property name="Note" column="note" />
    <many-to-one name="TypeInfo" class="TransactionType" column="tx_type" />
  </class>
</hibernate-mapping>

public class TransactionType
{
    public virtual string TransactionCode { get; set; }
    public virtual string Description { get; set; }
    public virtual decimal GLAccountNumber { get; set; }
    public virtual string Taxable { get; set; }
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" schema="aladdin" namespace="Receivables.Models">
  <class name="Receivables.Models.TransactionType, Receivables" lazy="false" table="txtype">
    <id name="TransactionCode" column="tx_code">
      <generator class="assigned" />
    </id>
    <property name="Description" column="description" />
    <property name="GLAccountNumber" column="gl_account_no" type="Decimal" />
    <property name="Taxable" column="taxable" />
  </class>
</hibernate-mapping>
公共类信用备忘录
{
公共虚拟内存ID{get;set;}
公共虚拟字符串编号{get;set;}
公共虚拟日期时间CreditDate{get;set;}
公共虚拟字符串InvoiceNumber{get;set;}
公共虚拟字符串ReturnToStock{get;set;}
发布的公共虚拟字符串{get;set;}
公共虚拟字符串注释{get;set;}
公共虚拟Iesi.Collections.Generic.ISet详细信息{get;set;}
公共虚拟销售发票发票信息{get;set;}
}
公共类详细信息
{
公共虚拟int CreditMemoDetailId{get;set;}
公共虚拟内存ID{get;set;}
公共虚拟字符串CreditType{get;set;}
公共虚拟十进制数{get;set;}
公共虚拟字符串影响{get;set;}
}
公共类销售发票
{
公共虚拟字符串InvoiceNumber{get;set;}
公共虚拟字符串Customer{get;set;}
公共虚拟日期时间InvoiceDate{get;set;}
公共虚拟字符串销售人员{get;set;}
Sale{get;set;}的公共虚拟字符串类
公共虚拟Iesi.Collections.Generic.ISet事务{get;set;}
}
公共类可接收记录
{
公共虚拟字符串InvoiceNumber{get;set;}
公共虚拟日期时间关联{get;set;}
公共虚拟字符串TxType{get;set;}
公共虚拟十进制数{get;set;}
公共虚拟字符串注释{get;set;}
公共虚拟事务类型TypeInfo{get;set;}
公共覆盖布尔等于(对象对象对象)
{
布尔结果=假;
尝试
{
可接收记录输入=(可接收记录)obj;
if(InvoiceNumber==input.InvoiceNumber&&AccrecDate==input.AccrecDate&&TxType==input.TxType)
{
结果=真;
}
}
捕获(例外情况除外)
{
}
返回结果;
}
公共覆盖int GetHashCode()
{
返回string.Format(“{0}{1}{2}”,InvoiceNumber,AccrecDate,TxType).GetHashCode();
}
}
公共类事务类型
{
公共虚拟字符串事务代码{get;set;}
公共虚拟字符串描述{get;set;}
公共虚拟十进制GLAccountNumber{get;set;}
公共虚拟字符串{get;set;}
}
存储库代码:

    public CreditMemo GetById(int id)
    {
        return NhSession.Get<CreditMemo>(id);
    }

    public SalesInvoice GetInvoiceByInvoiceNumber(string id)
    {
        SalesInvoice salesInvoice = NhSession.Get<SalesInvoice>(id);
        return salesInvoice;
    }
public CreditMemo GetById(int-id)
{
返回NhSession.Get(id);
}
public SalesInvoice GetInvoiceInVoiceNumber(字符串id)
{
SalesInvoice SalesInvoice=NhSession.Get(id);
退回销售发票;
}
替代GetInvoiceInVoiceNumber,它可以工作(即,它返回SalesInvoice下面的所有详细级别,而不更改映射):

返回NhSession.CreateQuery(“来自SalesInvoice,其中InvoiceNumber=:发票号”)
.SetString(“发票号”,id).UniqueResult();

可接收记录的Equals方法可能是问题所在,请将其更改为

public override bool Equals(object obj)
{
    ReceivablesRecord other = obj as ReceivablesRecord;
    return other != null &&
           InvoiceNumber == input.InvoiceNumber &&
           AccrecDate == input.AccrecDate &&
           TxType == input.TxType;
}

“当我执行Get(id)时,“-什么类型,什么id?”当我执行Get(invoiceNumber)时,“-我想你这里指的是Get(invoiceNumber)”-正确,但ISet是空的”-哪个集合?@Oskar我在Get的描述中很简短-实际代码在底部
1。获取(int-id)
2。获取(字符串id)
3。销售发票。交易记录。没有从SalesInvoice到CreditMemo的映射,因此我对CreditMemo.Details没有任何期望。不幸的是,到目前为止我还没有解决方案,但坦率地说,GetHashCode()实现非常糟糕:它可以经常调用,因此不应该使用像string.Format()这样的重方法。这种方法还会导致内存分配,为了提高性能,也应该避免内存分配。另一个问题是,它依赖于当前区域性进行日期格式设置,这可能会导致相同或“类似”对象在不同线程上生成不同的哈希代码,如果它们使用不同的区域性设置运行。相同的结果。FWIW我很确定我们的Equals方法在功能上是等价的,但你的方法更简洁、优雅。
public override bool Equals(object obj)
{
    ReceivablesRecord other = obj as ReceivablesRecord;
    return other != null &&
           InvoiceNumber == input.InvoiceNumber &&
           AccrecDate == input.AccrecDate &&
           TxType == input.TxType;
}