【问题标题】:Nhibernate building query休眠构建查询
【发布时间】:2018-07-25 01:26:39
【问题描述】:

我有一个可以在 MySql 中使用的查询,但我正在尝试在 Nhibernate 中使用它,但我遇到了问题,因为我是 Nhibernate 中的菜鸟。

SELECT transaction_table.transaction_id,transaction_table.amount,transaction_table.reason,transaction_table.transaction_datetime,g.status,
       (CASE
         WHEN (transaction_table.user_from IN(0)) THEN 'Paypal'
        when  (transaction_table.user_from<>0) THEN u.user_fullname
       END)as user_name_from ,
       (CASE
         WHEN (transaction_table.user_to IN(0)) THEN 'Paypal'
        when  (transaction_table.user_to<>0) THEN us.user_fullname
       END)as user_name_to 
FROM   transaction_table 
left outer join users u on u.user_id=transaction_table.user_from 
left outer join users us on  transaction_table.user_to=us.user_id 
left join gateway_table g on g.gateway_table_id=transaction_table.gateway_table_id

这是查询,

var results = session.QueryOver<TransactionTable>(() => transactionAlias)
                .Left.JoinAlias(pr => pr.UserFrom, () => usersFromAlias.Id)
                .Left.JoinAlias(pr => pr.UserTo, () => usersToAlias.Id)
                .Left.JoinAlias(pr => pr.GatewayTableId, () => gatewayAlias.GatewayTableId)
                .SelectList(list => list
                    .Select(pr => pr.TransactionId)
                    .Select(pr => pr.Amount)
                    .Select(pr => pr.Reason)
                    .Select(pr => pr.TransactionDatetime)
                    .Select(pr => pr.GatewayTableId)
                    .Select(Projections.Conditional(
                        Restrictions.Eq(
                            Projections.Property(() => transactionAlias.UserFrom), 0),
                        Projections.Constant("Paypal"),
                        Projections.Property(() => usersFromAlias.FullName)
                    ))
                    .Select(Projections.Conditional(
                        Restrictions.Eq(
                            Projections.Property(() => transactionAlias.UserTo), 0),
                        Projections.Constant("Paypal"),
                        Projections.Property(() => usersToAlias.FullName)
                    )))
                .List<object[]>();

在此之后我无法弄清楚如何进行,这是我一直在实施的中途。我找不到可靠的东西,关于 XML,我的映射可能是关系未映射的问题,我不知道该怎么做。

如下图:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="EWalletModule" namespace="EWalletModule">
  <!-- User Table -->
  <class name="Users" table="Users">
    <id name="Id" column="user_id" type="int">
      <generator class="native"></generator>
    </id>
    <property name="FullName" column="user_fullname" type="String"></property>
    <property name="Email" column="user_email" type="String"></property>
    <property name="Password" column="user_password" type="String"></property>
    <property name="CreatedDatetime" column="created_datetime" type="datetime"></property>
  </class>

  <!-- Transaction Table -->
  <class name="TransactionTable" table="transaction_table">
    <id name="TransactionId" column="transaction_id" type="int">
      <generator class="native"></generator>
    </id>
    <property name="GatewayTableId" column="gateway_table_id" type="int"></property>
    <property name="UserFrom" column="user_from" type="String"></property>
    <property name="UserTo" column="user_to" type="String"></property>
    <property name="Amount" column="amount" type="String"></property>
    <property name="Reason" column="reason" type="String"></property>
    <property name="TransactionDatetime" column="transaction_datetime" type="datetime"></property>
  </class>

  <!-- Gateway Table -->
  <class name="GatewayTable" table="gateway_table">
    <id name="GatewayTableId" column="gateway_table_id" type="int">
      <generator class="native"></generator>
    </id>
    <property name="Status" column="status" type="String"></property>
  </class>

  <!-- Wallet Table -->
  <class name="WalletTable" table="user_wallet">
    <id name="UserWalletId" column="user_wallet_id" type="int">
      <generator class="native"></generator>
    </id>
    <property name="UserId" column="user_id" type="int"></property>
    <property name="WalletBalance" column="wallet_balance" type="float"></property>
  </class>

  <!-- ManageWallet Table //For Admin -->
  <class name="ManageWalletTable" table="manage_wallet">
    <id name="ManageWalletId" column="manage_wallet_id" type="int">
      <generator class="native"></generator>
    </id>
    <property name="TransactionFee" column="transaction_fee" type="float"></property>
    <property name="WithdrawalFee" column="withdrawal_fee" type="float"></property>
    <property name="Tax" column="tax" type="float"></property>
  </class>
</hibernate-mapping>

表和映射一样简单,但是查询在Mysql工作台中工作,数据还可以,但不知道Nhibernate。 所以目前我遇到异常问题,我知道这是错误的,但不知道该怎么做,我不想使用简单的 sql 查询来做,我很乐意用 Object Way 做。

感谢 Stack-overflow 社区。​​p>

【问题讨论】:

    标签: c# mysql nhibernate


    【解决方案1】:

    JoinAlias 方法最常用的重载有 2 个参数:导航属性的表达式和别名的表达式。

    您不需要指定“开启”条件 - NHibernate 将使用映射来解决它。

    为此,您必须为UserFromUserToGatewayTable 添加导航属性。您可以保留旧属性,但将它们重命名为 UserFromId 并将类型更改为 int(并检查其他属性的类型:我猜 Amount 不应该是 string 而是 decimaldoubleint)。 如果您不能或不想添加导航属性,那么您将不得不使用子查询,因为据我所知,如果没有映射的导航属性,就无法在 NHibernate 中执行联接。

    var results = session.QueryOver<TransactionTable>(() => transactionAlias)
                    .Left.JoinAlias(pr => pr.UserFrom, () => usersFromAlias)
                    .Left.JoinAlias(pr => pr.UserTo, () => usersToAlias)
                    .Left.JoinAlias(pr => pr.GatewayTable, () => gatewayAlias)
                    .SelectList(list => list
                        .Select(pr => pr.TransactionId)
                        .Select(pr => pr.Amount)
                        .Select(pr => pr.Reason)
                        .Select(pr => pr.TransactionDatetime)
                        .Select(pr => pr.GatewayTableId)
                        .Select(Projections.Conditional(
                            Restrictions.Eq(
                                Projections.Property(() => transactionAlias.UserFromId), 0),
                            Projections.Constant("Paypal"),
                            Projections.Property(() => usersFromAlias.FullName)
                        ))
                        .Select(Projections.Conditional(
                            Restrictions.Eq(
                                Projections.Property(() => transactionAlias.UserToId), 0),
                            Projections.Constant("Paypal"),
                            Projections.Property(() => usersToAlias.FullName)
                        )))
                    .List<object[]>();
    

    另外我建议你创建一个自定义 Dto 模型并使用 ResultTransformer 而不是只返回元组:

    TransactionDto resultAlias = null;
    
    var results = session.QueryOver<TransactionTable>(() => transactionAlias)
                    .Left.JoinAlias(pr => pr.UserFrom, () => usersFromAlias)
                    .Left.JoinAlias(pr => pr.UserTo, () => usersToAlias)
                    .Left.JoinAlias(pr => pr.GatewayTable, () => gatewayAlias)
                    .SelectList(list => list
                        .Select(pr => pr.TransactionId).WithAlias(() => resultAlias.TransactionId)
                        .Select(pr => pr.Amount).WithAlias(() => resultAlias.Amount)
                        .Select(pr => pr.Reason).WithAlias(() => resultAlias.Reason)
                        .Select(pr => pr.TransactionDatetime).WithAlias(() => resultAlias.TransactionDatetime)
                        .Select(pr => pr.GatewayTableId).WithAlias(() => resultAlias.GatewayTableId)
                        .Select(Projections.Conditional(
                            Restrictions.Eq(
                                Projections.Property(() => transactionAlias.UserFromId), 0),
                            Projections.Constant("Paypal"),
                            Projections.Property(() => usersFromAlias.FullName)
                        )).WithAlias(() => resultAlias.UserFromName)
                        .Select(Projections.Conditional(
                            Restrictions.Eq(
                                Projections.Property(() => transactionAlias.UserToId), 0),
                            Projections.Constant("Paypal"),
                            Projections.Property(() => usersToAlias.FullName)
                        )).WithAlias(() => resultAlias.UserToName))
                    .TransformUsing(Transformers.AliasToBean<TransactionDto>())
                    .List<TransactionDto>();
    

    【讨论】:

    • 你好@Roman,你能帮我修改我的映射 xml 以使其正常工作吗?对不起,我是一个菜鸟,很难做到这一点。感谢您的帮助
    • 其实我没有xml映射的经验。我建议你使用FluentNhibernate
    • 好的,谢谢,我去看看
    【解决方案2】:

    我们需要的是关系映射。这由many-to-oneone-to-many 表示。文档

    5.1.11. many-to-one

    6.1. Persistent Collections

    所以,例如这个

    <property name="UserFrom" column="user_from" type="String"></property>
    

    应该是

    <many-to-one name="UserFrom"   column="user_from_id" class="User" />
    <property    name="UserFromId" column="user_from_id" type="Int32"  
                                        insert="false" update="false" />
    

    并且我们引用此类用户的实体应该具有属性

    public virtual User UserFrom { get; set; }
    public virtual int UserFromId { get; set; }
    

    第二个不是必需的。但有时可能有用。

    检查这些:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 2012-01-26
      • 2010-09-08
      • 2011-08-09
      相关资源
      最近更新 更多