无法在nhibernate中使用命名查询执行存储过程

时间:2013-05-27 13:18:06

标签: c# sql nhibernate fluent-nhibernate nhibernate-mapping

使用nhibernate执行存储过程时遇到奇怪的问题。当我通过堆栈跟踪然后我得到索引超出范围异常和属性/列的名称。我研究了谷歌和stackoverflow,发现如果任何属性被映射两次,那么它会导致问题。我检查了所有的映射,但似乎没有什么对我有帮助。 在这里,我正在编写我正在使用的所有hbl文件和代码。

Hbm文件代码

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="ConsoleApplication2" namespace="ConsoleApplication2" xmlns="urn:nhibernate-mapping-2.2">

    <class name="tARCustomer" table="tARCustomer" lazy="true" >
        <id name="fCustomerID">
            <generator class="guid.comb" />
        </id>
        <version name="fTimestamp" generated="always" unsaved-value="null" type="BinaryBlob">
            <!--<column name="fTimestamp" not-null="false" sql-type="timestamp"/>-->
        </version>
        <property name="fCustomerNumber">
        </property>
        <property name="fName">
        </property>
        <property name="fAddress1">
        </property>
        <property name="fAddress2">
        </property>
        <property name="fCity">
        </property>
        <property name="fLocalityID">
        </property>
        <property name="fPostalCode">
        </property>
        <property name="fDeliveryMethod">
        </property>
        <property name="fDoNotAllowFinanceCharges">
        </property>
        <property name="fNotes">
        </property>
        <property name="fInactive">
        </property>
        <property name="fCompanyID">
        </property>
        <property name="fPropertyID">
        </property>
        <property name="fEnterpriseID">
        </property>
        <property name="fDateAdded">
        </property>
        <property name="fAddedBy">
        </property>
        <property name="fDateModified">
        </property>
        <property name="fModifiedBy">
        </property>
        <property name="fShipToSameAsBilling">
        </property>
        <property name="fShipToAddress1">
        </property>
        <property name="fShipToAddress2">
        </property>
        <property name="fShipToCity">
        </property>
        <property name="fShipToLocalityID">
        </property>
        <property name="fShipToPostalCode">
        </property>
        <property name="fCustomerTotalBalance">
        </property>
        <property name="fSuspend">
        </property>
        <property name="fCreditLimitActive">
        </property>
        <property name="fCreditLimitAmt">
        </property>


        <bag name="Invoices" inverse="true" cascade="none" lazy="true">
            <key column="fCustomerID" />
            <one-to-many class="tARInvoice" />
        </bag>


        <many-to-one name="Enterprise" insert="false" update="false" cascade="none" class="ConsoleApplication2.tSCEnterprise,ConsoleApplication2"
            column="fEnterpriseID" not-null="false"/>



        <many-to-one name="Company" insert="false" update="false" cascade="none" class="ConsoleApplication2.tSCCompany,ConsoleApplication2"
            column="fCompanyID" not-null="false"/>



        <many-to-one name="Property" insert="false" update="false" cascade="none" class="ConsoleApplication2.tSCProperty,ConsoleApplication2"
            column="fPropertyID" not-null="false"/>


    </class>

    <!--<loader query-ref="ar_tARCustomer_ReadOverdueByContext"/>-->

    <sql-query name="ar_tARCustomer_ReadOverdueByContext" >
        <return class="tARCustomer">
        </return>
        exec ar_tARCustomer_ReadOverdueByContext :CustomerActive ,:CompanyID,:PropertyID ,:DateFrom, :DateTo, :InvoiceTypes
    </sql-query>

</hibernate-mapping>

和域类代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    [Serializable]
    public class tARCustomer 
    {
        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="tARCustomer"/> class.
        /// </summary>
        public tARCustomer()
        {

        }

        /// <summary>
        /// Initializes a new instance of the <see cref="tARCustomer"/> class.
        /// </summary>
        /// <param name="fCustomerID">The Payment Type ID.</param>
        public tARCustomer(System.Guid fCustomerID)
        {
            ////base.ID = fCustomerID;
        }
        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets customer ID.
        /// </summary> 
        public virtual System.Guid fCustomerID { get; set; }

        public virtual string fCustomerNumber { get; set; }

        public virtual string fName { get; set; }

        public virtual string fAddress1 { get; set; }

        public virtual string fAddress2 { get; set; }

        public virtual string fCity { get; set; }

        public virtual Guid? fLocalityID { get; set; }

        public virtual string fPostalCode { get; set; }

        public virtual string fDeliveryMethod { get; set; }

        public virtual bool fDoNotAllowFinanceCharges { get; set; }

        public virtual string fNotes { get; set; }

        public virtual bool fInactive { get; set; }

        public virtual bool fSuspend { get; set; }

        public virtual bool fCreditLimitActive { get; set; }

        public virtual decimal fCreditLimitAmt { get; set; }

        public virtual Guid? fCompanyID { get; set; }

        public virtual Guid? fPropertyID { get; set; }

        public virtual Guid? fEnterpriseID { get; set; }

        public virtual DateTime? fDateAdded { get; set; }

        public virtual string fAddedBy { get; set; }

        public virtual DateTime? fDateModified { get; set; }

        public virtual string fModifiedBy { get; set; }

        public virtual byte[] fTimestamp { get; set; }

        public virtual bool fShipToSameAsBilling { get; set; }

        public virtual string fShipToAddress1 { get; set; }

        public virtual string fShipToAddress2 { get; set; }

        public virtual string fShipToCity { get; set; }

        public virtual Guid? fShipToLocalityID { get; set; }

        public virtual string fShipToPostalCode { get; set; }

        public virtual decimal fCustomerTotalBalance { get; set; }        

        #endregion


        public virtual tSCCompany Company { get; set; }
        public virtual tSCProperty Property { get; set; }
        public virtual tSCEnterprise Enterprise { get; set; }

        public virtual IList<tARInvoice> Invoices { get; set; }


        #region Methods
        /// <summary>
        /// To retrieve Hash Code.
        /// </summary>
        /// <returns>The retrieve hash code.</returns>
        public override int GetHashCode()
        {
            return this.GetHashCode();            
        }
        #endregion
    }
}

我使用以下代码来调用sp。

var dd = session.GetNamedQuery("ar_tARCustomer_ReadOverdueByContext")
                       .SetParameter("CustomerActive", 2)
                       .SetParameter("CompanyID", Guid.Parse("3C5F1D66-75F3-4762-BAA1-6A0ADA8D6DD4"))
                       .SetParameter("PropertyID", Guid.Parse("53C4B765-C1B1-4353-98CB-AC9FBCE84F0C"))
                       .SetParameter("DateFrom", DateTime.Parse("5/1/2001"))
                       .SetParameter("DateTo", DateTime.Parse("4/24/2013"))
                       .SetParameter("InvoiceTypes", "Manual")
                       .SetResultTransformer(new AliasToBeanResultTransformer(typeof(tARCustomer)))
                       .SetResultTransformer(Transformers.ToList).List();

除此之外我尝试了很多组合,但我无法解决它。 我有以下存储过程。

alter PROCEDURE [dbo].[ar_tARCustomer_ReadOverdueByContext]  

  @CustomerActive  int,      
  @CompanyID   uniqueidentifier,   
  @PropertyID   uniqueidentifier,   
  @OverdueDateFrom  datetime,   
  @OverdueDateTo  datetime,   
  @InvoiceTypes   varchar(100)  

AS  

----------------------------------------------------------------------------    
-- Name:     ar_tARCustomer_ReadOverdueByContext    
-- Purpose:  Get all customers with overdue invoices matching the given criteria at this point in the hierarchy       
--    
-- Input:    N/A    
-- Output:   Recordset containing all customers with overdue invoices matching the given criteria  
-- Return:   0 = Success    
--           >0 = Error    
--    
----------------------------------------------------------------------------    

SET NOCOUNT ON;  -

SELECT fName
from tARCustomer 

我想说的另一件事是,当我使用select * from tARCustomer时,这个程序对我有用,但是当我使用来自tARCustomer的select fCustomerID时,它会给出错误。

我不知道为什么会这样,但我无法解决它。请帮我尽快解决这个问题,

这里我将堆栈跟踪异常。

NHibernate.Exceptions.GenericADOException was caught
  Message=could not execute query
[ exec ar_tARCustomer_ReadOverdueByContext @p0 ,@p1,@p2 ,@p3, @p4, @p5 ]
  Name:CustomerActive - Value:2  Name:CompanyID - Value:3c5f1d66-75f3-4762-baa1-6a0ada8d6dd4  Name:PropertyID - Value:53c4b765-c1b1-4353-98cb-ac9fbce84f0c  Name:DateFrom - Value:5/1/2001 12:00:00 AM  Name:DateTo - Value:4/24/2013 12:00:00 AM  Name:InvoiceTypes - Value:Manual
[SQL: exec ar_tARCustomer_ReadOverdueByContext @p0 ,@p1,@p2 ,@p3, @p4, @p5]
  Source=NHibernate
  SqlString=exec ar_tARCustomer_ReadOverdueByContext @p0 ,@p1,@p2 ,@p3, @p4, @p5
  StackTrace:
       at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
       at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
       at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
       at NHibernate.Loader.Custom.CustomLoader.List(ISessionImplementor session, QueryParameters queryParameters)
       at NHibernate.Impl.SessionImpl.ListCustomQuery(ICustomQuery customQuery, QueryParameters queryParameters, IList results)
       at NHibernate.Impl.SessionImpl.List(NativeSQLQuerySpecification spec, QueryParameters queryParameters, IList results)
       at NHibernate.Impl.SessionImpl.List(NativeSQLQuerySpecification spec, QueryParameters queryParameters)
       at NHibernate.Impl.SqlQueryImpl.List()
       at ConsoleApplication2.Program.Main(String[] args) in E:\Test\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
  InnerException: System.IndexOutOfRangeException
       Message=fCustomerID
       Source=System.Data
       StackTrace:
            at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName)
            at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)
            at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name)
            at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name)
            at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
            at NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session)
            at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
            at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
            at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
            at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
       InnerException: 

感谢。

1 个答案:

答案 0 :(得分:0)

当您对查询结果使用AliasToBeanResultTransformer时,查询中返回的列必须与您要加载数据的类的属性一对一映射。

您在上面发布的查询只返回一列fName1 - 它缺少您的班级tARCustomer的所有其他属性。

抛出的异常告诉您问题 - 它无法找到结果列fCustomerID。为了说明修改你的select语句以包含它并重新运行它,异常将突出显示下一个缺失的字段。