如何将NamedSQLQueryDefinition类动态地用作sql-query等价物?

时间:2010-08-04 21:04:57

标签: nhibernate fluent-nhibernate

我需要动态地将命名查询添加到NHibernate配置对象。搜索引擎返回几个引用NamedSQLQueryDefinition或NamedQueryDefinition的命中。以下是我正在尝试做的事情。我不知道如何为NamedSQLQueryDefinition构造函数提供成功创建查询的内容。任何人都可以提供一个如何以正确的方式创建新的NamedSQLQueryDefinition的示例吗?谢谢!

会话初始化程序:

    private static ISessionFactory CreateSessionFactory()
    {
        var configuration = new Configuration();

        return Fluently.Configure(configuration.Configure())
            .ExposeConfiguration(AddQueries)
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>())
            .Mappings(m => m.HbmMappings.AddFromAssemblyOf<Program>())
            .BuildConfiguration()
            .BuildSessionFactory();
    }

AddQueries看起来像这样:

    private static void AddQueries(Configuration cfg)
    {
        var nameQuery = new NamedSQLQueryDefinition("exec pr_GETCustomer ?", ...)

        cfg.NamedSQLQueries.Add("pr_GETCustomer", nameQuery);
        var cust = cfg.GetClassMapping(typeof (Customer));

        cust.LoaderName = "pr_GETCustomer";
    }

PS:我正在尝试这条路线,因为Fluent NHibernate没有实现配置加载器和放大器的方法。来自hbm文件的sql-query元素。

2 个答案:

答案 0 :(得分:1)

AddQueries方法将按如下方式实现,以“修复”Fluent NHibernate缺少Loader支持。诀窍是正确设置INativeSQLQueryReturn []值以包含从表列到实体属性的映射。它应该模仿HBM文件中sql-query的return元素的内容,其中定义了类(带命名空间)和属性映射(参见下面的XML)。感谢@jimbobmcgee让我开始朝着这个方向前进!

private static void AddQueries(Configuration cfg)
{
    var namedQuery = new NamedSQLQueryDefinition(
        "exec dbo.pr_GETCustomers @CustomerID=?",
        new INativeSQLQueryReturn[]
            {
                new NativeSQLQueryRootReturn(
                    "Customers",
                    "VehicleInfo.Entities.Customers",
                    new Dictionary<string, string[]>
                        {
                                    {"CustomerID", new[] {"CustomerID"}},
                                    {"CompanyName", new[] {"CompanyName"}}
                    },
                    LockMode.Read)
            },
        new List<string> { "dbo.Customers" },
        true,
        null,
        15,
        1000,
        FlushMode.Auto,
        CacheMode.Normal,
        false,
        "",
        null,
        true);

    cfg.NamedSQLQueries.Add("pr_GETCustomers", namedQuery);
    var cust = cfg.GetClassMapping(typeof(Customers));

    cust.LoaderName = "pr_GETCustomers";
}

样本HBM文件执行相同的操作:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    default-access="property" auto-import="true" 
    default-cascade="none" default-lazy="true">
    <class xmlns="urn:nhibernate-mapping-2.2"
        mutable="true" name="VehicleInfo.Entities.Customers, VehicleInfo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Customers">
        <id name="CustomerID" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <column name="CustomerID" />
            <generator class="assigned" />
        </id>

        <property name="CompanyName" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <column name="CompanyName" />
        </property>

        <loader query-ref="pr_GETCustomers"/>

        <sql-insert callable="true" check="none">exec dbo.pr_INSERTCustomers @CompanyName=?, @CustomerID=?</sql-insert>
        <sql-update callable="true" check="none">exec dbo.pr_UPDATECustomers @CompanyName=?, @CustomerID=?</sql-update>
        <sql-delete callable="true" check="none">exec dbo.pr_DELETECustomers @CustomerID=?</sql-delete>
    </class>
    <sql-query name="pr_GETCustomers">
        <return alias="cust" class="VehicleInfo.Entities.Customers, VehicleInfo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
            <return-property name="CustomerID" column="CustomerID"></return-property>
            <return-property name="CompanyName" column="CompanyName"></return-property>
        </return>
        exec dbo.pr_GETCustomers @CustomerID=?
    </sql-query>
</hibernate-mapping>

答案 1 :(得分:0)

我对此很新,但大多数参数看起来都可以从您在HBM文件中提供的属性中确定。也就是说,我不太确定QuerySpaces是什么。我最接近我认为你想要实现的是使用以下(未经测试):

ISQLQuery q = session.CreateSQLQuery("exec pr_GETCustomer :p1");

if (q is SqlQueryImpl)
{
    IDictionary<string, TypedValue> namedParams = new Dictionary<string, TypedValue>();
    namedParams.Add("p1", new TypedValue(NHibernateUtil.Int32, 12345);

    IDictionary<string, string> paramTypes = new Dictionary<string, string>();

    NativeSQLQuerySpecification spec = 
        (q as SqlQueryImpl).GenerateQuerySpecification(namedParams);

    NativeSQLQueryDefiniton def = new NativeSQLQueryDefiniton(
        spec.QueryString,
        spec.SqlQueryReturns,
        spec.QuerySpaces,
        false,
        null,
        -1,
        -1,
        FlushMode.Never,
        CacheMode.Normal,
        true,
        "blah",
        paramTypes,
        false
    );
}

显然,我不喜欢转换为SqlQueryImpl。我希望,一旦我们中的一个人做过一次,就可以理解像querySpaces这样的模糊属性,所以你不必这样做。

并不是说我希望它100%有效,但从这里可能更容易实现。