NHibernate linq - 在映射时使用lambda表达式代替公式属性

时间:2010-02-09 23:34:12

标签: sql linq nhibernate

NHibernate在名为“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&gt; 0 选择i;

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

4 个答案:

答案 0 :(得分:1)

由于您已在对象上拥有Amount和Paid属性,因此您只需将Balance属性定义为常规属性:

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

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

之类的陈述
invoices.Where(i => i.Balance > 5)

会导致集合中每个发票的数据库访问权限 这可能仍然可以为您所接受,请注意这一点 干杯 的Jhonny

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

到目前为止,我见过的最先进的方法是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中创建原因的详细信息。