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查询?
答案 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中创建原因的详细信息。