使用Fluent NHibernate定义派生的布尔属性

时间:2012-12-19 17:10:15

标签: nhibernate fluent-nhibernate fluent-nhibernate-mapping

我有一个班级

public class Account {

   public DateTime? StartDate {get;set;}

   public DateTime? EndDate {get;set;}

   public bool IsActive {get;set;}

}

IsActive属性被定义为公式

.Formula(" StartDate < GETDATE() and (EndDate is NULL or EndDate > GetDate())")

但是当使用QueryOver查询IsActive == true的所有Account时,我得到一个NHibernate无法执行SQL的错误。

NHibernate生成的SQL

...other criterias...
and this_.StartDate < GETDATE()
   and (this_.EndDate is NULL 
         or this_.EndDate > GetDate()) = 1

如何正确定义公式。

Formula是正确的方法,还是有一种完全不同的方式来实现它

更新:

  • 有没有办法在不改变底层数据库的情况下做到这一点

由于

3 个答案:

答案 0 :(得分:3)

在这种情况下,Formula应该/必须返回bool。因此,我们可以通过这种方式重新定义公式(SQL Serever语法)

.Formula(@"
(
  CASE
    WHEN  StartDate < GETDATE() and (EndDate is NULL or EndDate > GetDate())
     THEN 1
     ELSE 0
  END
)
";

括号不需要,但是......)返回值为1或0表示bool。现在这个QueryOver将起作用:

var query = session.QueryOver<Account>()
           .Where(a => a.IsActive == true);
var list = query.List<Account>();

答案 1 :(得分:0)

将表格本身的公式定义为computed column。这样做的好处是可以在NHibernate之外工作,而无需复制公式逻辑。您需要通知您的NHibernate映射它永远不应该尝试通过将“Generated”设置为计算列来写入计算列。

答案 2 :(得分:0)

我认为这会有效但我没有用NHibernate测试它以确保条件被正确解释。您必须使用此方法使用LINQ查询。您也可以使用扩展方法采用类似的方法。

public class Account
{
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public bool IsActive
    {
        get { return AccountIsActive(this); }
    }

    public static readonly Func<Account, bool> AccountIsActive = a =>
        {
            var now = DateTime.Now;
            return (a.StartDate.HasValue && a.StartDate < now) && (!a.EndDate.HasValue || a.EndDate > now);
        };
}

用法:

var activeAccounts = session.Query<Account>()
                     .Where(a => Account.AccountIsActive(a))
                     .ToList();