.net NHibernate-如何映射到没有表的类(用于自定义sql查询)

.net NHibernate-如何映射到没有表的类(用于自定义sql查询),.net,nhibernate,fluent-nhibernate,.net,Nhibernate,Fluent Nhibernate,更新-为可读性编辑配置 如此 嗨 我学习NHibernate已经有一两天了,但有一点被卡住了 我需要能够执行自定义存储过程,并使用NHibernate将它们映射回域类 我将此应用于这样一个场景:自定义查询映射回映射到数据库表的对象,如许多nhibernate示例所示(请参见下面的第一节) 但是,在下面第二节的配置中,查询只从目标表中提取2列。出于这个原因,我创建了一个自定义对象,以便NHibernate能够将返回值映射到其中。自定义对象属性与自定义过程中的返回列具有相同的名称 当我运行测试时,会

更新-为可读性编辑配置 如此

我学习NHibernate已经有一两天了,但有一点被卡住了

我需要能够执行自定义存储过程,并使用NHibernate将它们映射回域类

我将此应用于这样一个场景:自定义查询映射回映射到数据库表的对象,如许多nhibernate示例所示(请参见下面的第一节)

但是,在下面第二节的配置中,查询只从目标表中提取2列。出于这个原因,我创建了一个自定义对象,以便NHibernate能够将返回值映射到其中。自定义对象属性与自定义过程中的返回列具有相同的名称

当我运行测试时,会出现如下异常:

NHibernate.MappingException:否 持久化器用于: Proj.DataEntityTracker.Domain.Entities.CustomObject

所以我猜sql查询部分下的映射不足以让NHibernate将返回值映射到对象属性

所以我的问题是-如何设置数据库中没有等效表的映射,以便将存储过程的结果映射到该对象

<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Proj.DataEntityTracker.Domain" namespace="Proj.DataEntityTracker.Domain.Entities"> <class name="TrackedEntityProperty" table="TrackedEntityProperties"> <id name="ID" type="Int32" unsaved-value="0"> <generator class="native"></generator> </id> <property name="TrackedEntityID" /> <property name="Name" /> <property name="CreatedDate" /> <property name="ChangedDate" /> <property name="DataType" /> <property name="CurrentValue" /> <property name="RequestPropertyValueQuestion" /> <property name="NullResponseIsAcceptable" /> <property name="Duplication" /> <property name="Frequency" /> <property name="IsActive" /> <property name="IsDeleted" /> <property name="LastUpdateTaskGenerated" /> <property name="LastUpdateTaskCompleted" /> <property name="LastUpdateTaskCancelled" /> </class> <sql-query name="usp_GetTrackedEntityPropertiesDueForUpdate" > <return alias="usp_GetTrackedEntityPropertiesDueForUpdate" class="TrackedEntityProperty"> <return-property name="ID" column="ID" /> <return-property name="TrackedEntityID" column="TrackedEntityID" /> <return-property name="Name" column="Name" /> <return-property name="CreatedDate" column="CreatedDate" /> <return-property name="ChangedDate" column="ChangedDate" /> <return-property name="DataType" column="DataType" /> <return-property name="CurrentValue" column="CurrentValue" /> <return-property name="RequestPropertyValueQuestion" column="RequestPropertyValueQuestion" /> <return-property name="NullResponseIsAcceptable" column="NullResponseIsAcceptable" /> <return-property name="Duplication" column="Duplication" /> <return-property name="Frequency" column="Frequency" /> <return-property name="IsActive" column="IsActive" /> <return-property name="IsDeleted" column="IsDeleted" /> <return-property name="LastUpdateTaskGenerated" column="LastUpdateTaskGenerated" /> <return-property name="LastUpdateTaskCompleted" column="LastUpdateTaskCompleted" /> <return-property name="LastUpdateTaskCancelled" column="LastUpdateTaskCancelled" /> </return> exec usp_GetTrackedEntityPropertiesDueForUpdate :TrackedEntityID </sql-query> <sql-query name="usp_SomeCustomSproc"> <return alias="usp_SomeCustomSproc" class="CustomObject"> <return-property name="ID" column="ID" /> <return-property name="Name" column="Name" /> </return> exec usp_SomeCustomSproc :TrackedEntityID </sql-query> </hibernate-mapping> exec usp_GetTrackedEntityProperties DueforUpdate:TrackedEntityID 执行usp_SomeCustomSproc:TrackedEntityID
你要找的是投影。首先,您需要修改查询

  <sql-query name="usp_SomeCustomSproc">
    <return-scalar column="Id" type="Int32"/>
    <return-scalar column="Name" type="String"/>

    exec usp_SomeCustomSproc :TrackedEntityID

  </sql-query>

执行usp_SomeCustomSproc:TrackedEntityID
然后在调用它的代码中指定一个结果转换器。AliasToBeanTransformer将获取列别名并将其映射到对象上的属性

session.GetNamedQuery("usp_SomeCustomSproc")
       .SetInt32("TrackedEntityID", 15)
       .SetResultTransformer(Transformers.AliasToBean<CustomObject>())
       .List<CustomObject>()
session.GetNamedQuery(“usp\u SomeCustomSproc”)
.SetInt32(“TrackedEntityID”,15)
.SetResultTransformer(Transformers.AliasToBean())
.List()

问题已解决,尽管NHibernate显然不希望您使用存储过程。我发布这篇文章是为了帮助其他人解决同样的问题,因为这些信息不容易获得

虽然这个例子将结果映射回了一个标准的对象-表映射(这可能是您想要的)。我想将结果映射回数据库中没有表表示形式的自定义对象:

因此,我创建了一个域类来保存存储过程结果

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

namespace MyProj.DataEntityTracker.Domain.Entities
{
    public class DemoCustomSprocObj
    {
        public virtual Guid Guid { get; set; }
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }
    }
}
虽然我发现确实需要创建一个类定义(没有表属性),以避免“NHibernate.MappingException:no persister for:”类型错误,但该类在SQL server中不必有相应的表

还要注意,为保存存储过程结果而创建的域类需要一个ID字段,并且必须从数据库返回该字段。在本例中,我从SQL Server返回了NEWID(),并将映射类配置为使用ID字段的GUID生成器

CREATE PROCEDURE usp_DemoCustomSproc
  @TrackedEntityID INT
AS
SET NOCOUNT ON
BEGIN
    SELECT NEWID() AS [Guid],
           ID ,
           Name 
    FROM TrackedEntityProperties AS tep
    WHERE TrackedEntityID = @TrackedEntityID
END
以及映射类:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MyProj.DataEntityTracker.Domain"
                   namespace="MyProj.DataEntityTracker.Domain.Entities">

  <!-- This mapping does not use a table, rather it exists to
  allow the mapping of a stored procedure result back to a domain object. 
  Note the use of the GUID. An ID must be present and returned by the stored 
  procedure result, otherwise the object will not work with NHibernate.
  Note also the absence of a table in the class tag. No table exists in
  the database, but the mapping must exist to avoid "No persiter" errors.

  Arguments are passed with the :Arg syntax.

  It seems that NHibernate was not designed for use with stored procedures,
  though it may be useful to be able to use them in some situations. This
  is a means of doing so.

  -->

  <class name="DemoCustomSprocObj">
    <id name="Guid" type="guid" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid"></generator>
    </id>
    <property name="ID" />
    <property name="Name" />
  </class>

  <sql-query name="usp_DemoCustomSproc">
    <return alias="usp_DemoCustomSproc" class="DemoCustomSprocObj">

      <return-property name="Guid" column="Guid" />
      <return-property name="ID" column="ID" />
      <return-property name="Name" column="Name" />

    </return>

    exec usp_DemoCustomSproc :TrackedEntityID

  </sql-query>

</hibernate-mapping>

执行usp_DemoCustomSproc:TrackedEntityID

添加类也解决了我的命名查询问题。谢谢