【问题标题】:NHibernate linq - Use lambda expression in place of formula attribute on mappingNHibernate linq - 在映射上使用 lambda 表达式代替公式属性
【发布时间】:2010-02-09 23:34:11
【问题描述】:

NHibernate 在映射配置中的 property 元素上有一个名为“formula”的属性,它允许注入 sql 来“计算”一个属性。我遇到的问题是直接使用 sql 语法的公式。有没有办法让 nhibernate.linq 使用 lambda 表达式而不是使用公式属性。

我有以下几点:

public class Invoice
{
    public virtual int Id { get; protected set; }
    public virtual decimal Amount { get; set; }
    public virtual decimal Paid { get; set; }
    public virtual decimal Balance
    {
        get { return BalanceExpression.Expression.Compile().Invoke(this); }
    }
}

public class BalanceExpression
{
    public static Expression<Func<Invoice, decimal>> Expression
    {
        get { return i => i.Amount - i.Paid; }
    }
}

<class name="Invoice"> 
  <id name="Id"> 
    <generator class="hilo"/> 
  </id> 
  <property name="Amount"/> 
  <property name="Paid"/> 
  <property name="Balance" formula="Amount - Paid" access="readonly"/> 
</class>

我希望 nhibernate 使用 balanceexpression.expression 而不必将 sql 语法放在公式属性中,这样我就可以从我的映射配置中删除公式属性并编写如下查询:

来自 session.linq() 中的 i 其中 i.balance > 0 选择我;

如何将 balanceexpression.expression 注入到 linq 查询中?

【问题讨论】:

    标签: sql linq nhibernate


    【解决方案1】:

    由于您的对象已经有了 Amount 和 Paid 属性,您可以将 Balance 属性定义为常规属性:

    public int Balance { get { return Amount - Paid; } }
    

    如果您不将 Amount / Paid 属性设置为“Lazy”,我认为这是最好的、最易读且最可维护的解决方案。
    如果这些属性中的任何一个是延迟加载的,您仍然可以使用此方法,只需注意它会产生副作用。 例如 - 这样的语句

    invoices.Where(i => i.Balance > 5)
    

    将导致集合中每个 Invoice 的数据库访问。
    这对您来说可能仍然可以接受,请注意这一点..
    干杯 强尼

    【讨论】:

      【解决方案2】:

      我很确定 http://hendryluk.wordpress.com/2011/09/06/nhibernate-linq-ing-calculated-properties/ 就是您要找的东西。 (“更好的方式?”部分)

      【讨论】:

        【解决方案3】:

        只有 sql 表达式可以用作公式,请查看文档 - http://www.nhforge.org/doc/nh/en/#mapping-declaration-property 。这是因为它直接进入数据库中列的公式属性(使用此公式创建计算列)。
        不要把事情搞得太复杂,用那个sql公式就行了。如果您认为该表达式会更快 - 那您就错了。

        【讨论】:

          【解决方案4】:

          目前我见过的最高级的方式是NHibernate.Property.Expression

          来自他们的网站:

          public class Person
          {
              public virtual Guid Id { get; set; }
              public virtual string Name { get; set; }
              public virtual DateTime StartDate { get; set; }
              public virtual DateTime? EndDate { get; set; }
              public virtual Person Manager { get; set; }
          
              public static Expression<Func<Person, bool>> IsActiveExpression =
                  person => person.StartDate <= DateTimeTestable.Today() && (person.EndDate == null || person.EndDate >= DateTimeTestable.Today());
          
              public static Func<Person, bool> CompiledIsActive = IsActiveExpression.Compile(); 
          
              public virtual bool IsActive { get { return CompiledIsActive(this); } }
          }
          

          查询:

          session.QueryExtended<Person>().Where(p => p.IsActive)
          

          这类似于 dvdvorle 发布的内容,但应该解决一些问题(例如需要参数名称与原始表达式和where 子句中的参数名称完全匹配)。更多关于它为什么在this article创建的信息。

          【讨论】:

            猜你喜欢
            • 2023-03-26
            • 1970-01-01
            • 2023-03-12
            • 2015-07-05
            • 1970-01-01
            • 2016-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多