代码之家  ›  专栏  ›  技术社区  ›  Sixto Saez

NamedSQLQueryDefinition类如何作为sql查询等价物动态使用?

  •  1
  • Sixto Saez  · 技术社区  · 15 年前

    会话初始值设定项:

        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没有实现配置loader&的方法;hbm文件中的sql查询元素。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Sixto Saez    15 年前

    AddQueries方法将按以下方式实现,以“修复”Fluent NHibernate缺少加载程序支持的问题。诀窍是正确设置INativeSQLQueryReturn[]值,以包含从表列到实体属性的映射。它应该模拟HBM文件中sql query的return元素的内容,在HBM文件中定义了类(带有名称空间)和属性映射(参见下面的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>
    
        2
  •  0
  •   jimbobmcgee    15 年前

    我对此非常陌生,但是大多数参数看起来都是可以从HBM文件中提供的属性中确定的。也就是说,我不太确定查询空间是什么。我认为你想要达到的最接近的目标是使用以下方法(未经测试):

    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%的工作,但它可能会更容易实现从这里。