NHibernate - 如何获取未被另一个表中的项引用的项

时间:2009-12-03 21:30:14

标签: nhibernate

假设我有一个课程凭证:

public class Voucher
{
    public Guid Id {get;set;}
    public DateTime DateAvailable {get;set;}
}

和一个类条目

public class Entry
{
    public Guid Id {get;set;}
    public Voucher Voucher {get;set;}
    // ... other unrelated properties
}

如何创建NHibernate Criteria查询,以查找当前未分配给条目的第一个可用凭证?

等效的SQL将是

select 
    v.Id, v.DateAvailable 
from 
    Voucher v
        left join Entries e on e.VoucherId = v.Id
where 
    v.DateAvailable <= getutcdate() and
    e.Id is null

编辑:我仍然无法解决这个问题。凭证表没有对条目表的引用,但我需要找到尚未分配给条目的第一个凭证(按日期顺序)。这看起来像是一个简单的任务,但是我一直在阅读关于使用NHibernate标准的所有内容左连接都要求Voucher对象具有引用该条目的属性。当然有一种方法可以反转查询或向Voucher对象添加引用属性,而无需修改数据库以使每个表引用另一个。

编辑2:对于它的价值,我认为没有一些修改就可以做我想做的事情。我最终得到了一个查询,使用Entry作为主要标准,将凭证作为子标准,但随后UniqueResult返回null,即使数据存在。我想它只是无法建立关联。

如果有人遇到这种情况,我最终在每个表中引用另一个外键并使用References&lt;&gt;映射以关联两者。这不是主意,因为我必须手动将每个实体的子属性设置为另一个以使关联双向,但它至少可以在没有大量更改的情况下工作。

3 个答案:

答案 0 :(得分:1)

以下内容应该可以使用HQL:

IQuery query = session.CreateQuery(@"
    FROM
        Voucher v LEFT JOIN
        Entry e
    WHERE
        e.ID IS NULL AND
        v.DateAvailable <= :now
");

query.SetParameter("now", DateTime.Now);

// If you want to restrict to only the first result
query.SetMaxResults(1);
Voucher v = query.UniqueResult<Voucher>();

// Otherwise, get a list of results...
// List<Entry> results = query.List<Entry>();

答案 1 :(得分:1)

按字面翻译SQL:

var voucher = NHibernateSessionManager.Session.CreateCriteria<Voucher>("v")
                        .Add(Restrictions.Le("v.DateAvailable", DateTime.UtcNow))
                        .CreateCriteria("Entries", "e")
                        .Add(Restrictions.IsNull("e.Id"))
                        .SetMaxResults(1)
                        .UniqueResult<Voucher>();

现在,如果我理解正确,可能会有一些改变。 如果声明:“..查找当前未分配给条目的第一个可用凭证...”与法规“查找没有条目的第一个可用凭证...”相同(因为凭证是有许多条目的实体......根据你的类)然后你可以这样做:

var voucher = NHibernateSessionManager.Session.CreateCriteria<Voucher>()
                .Add(Restrictions.IsEmpty("Entries"))
                .Add(Restrictions.Le("DateAvailable", DateTime.UtcNow))
                .SetMaxResults(1)
                .UniqueResult<Voucher>();

...假设您已在凭证实体中映射了Entries属性。

但也许我弄错了......

答案 2 :(得分:0)

从记忆中,可能不起作用:

session.CreateQuery<Entry>().CreateAlias("Voucher","v").Add(Restrictions.And(
    Restrictions.Lt("DateAvailable",DateTime.Now),
    Restrictions.Eq("v.Id",null")
).List<Voucher>();