在NHibernate查询中基于不同表设置值

5
我正在使用NHibernate,遇到了这个查询的问题...我有一个名为Item的类,想要通过它的ID来获取它。一切都很好。然而,如果设置了其他条件,我还想在Item类上设置一个布尔属性为true。具体来说,这个属性被命名为IsMarked,告诉用户是否将该项目标记/星号/标记为请求它的用户,并且此信息设置在给出Item和User之间关系的表上。
目前,我正在获取Item,然后查找引用——如果找到引用,则将属性更新为true。我能否在一个查询中完成这个操作?
var item = Session.Get<Item>(itemId);

var flaggedResult = Session.CreateCriteria<ItemWithUserFlag>()
    .Add(Restrictions.Eq("User.Id", userId))
    .Add(Restrictions.Eq("Item", item))
    .List<ItemWithUserFlag>();

if (flaggedResult.Count > 0)
    item.IsMarked = true; 

return item; 

你的类是如何映射的?用户和物品之间有多对多的关系吗? - Søren Randrup
我正在使用Fluent进行映射。在一个单独的类ItemWithUserFlag中表示了多对多关系。用户没有与物品直接相关联,物品也没有与用户直接相关联。ItemWithUserFlag具有对用户和物品的引用集合。 - stiank81
1个回答

7

如何在属性映射中使用formulafilter

<property name="IsMarked" formula="(select count(*) from ItemWithUserFlag where ItemWithUserFlag.ItemId = ItemId and ItemWithUserFlag.UserId = :UserFilter.userId)" />

并过滤def:

<filter-def name="UserFilter">
    <filter-param name="userId" type="Int32"/>
</filter-def>

那将会得到类似这样的结果。
SELECT Item.*, (select count(*) from ItemWithUserFlag where ItemWithUserFlag.ItemId = Item.ItemId and ItemWithUserFlag.UserId = ?) AS IsMarked FROM Item

只要将IsMarked定义为bool类型,如果count(*)返回0,它将被转换为false,如果返回任何> 0的值,它将被转换为true

编辑:流畅的表示方法

public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        /// ... whatever
        Map(x => x.IsMarked).Formula("(select count(*) from ItemWithUserFlag where ItemWithUserFlag.ItemId = ItemId and ItemWithUserFlag.UserId = :UserFilter.userId)");
    }
}

public class UserFilter : FilterDefinition
{
    public UserFilter()
    {
        WithName("UserFilter")
            .AddParameter("userId", NHibernate.NHibernateUtil.Int32);
    }
}

谢谢!还没有测试,但听起来这应该会起作用。问题在于我使用FluentNhibernate进行映射。不知道我是否可以同时定义一些XML映射,或者是否可以用Fluent表达相同的映射。所以,没有办法直接在查询中实现这个吗? - stiank81
@stiank81 关于在查询中实现这一点:我认为没有任何方法。从逻辑上讲,你想要的不是限制或其他什么,而是一个计算列,所以我认为必须通过映射来完成。但是,我对nHibernate并不是很专业,因此无法确定告诉你。 - František Žiačik
谢谢您的编辑!现在无法测试,但我会回复您的。 - stiank81

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接