【问题标题】:How do I use NHibernate CreateCriteria for joins with possible null value?如何使用 NHibernate CreateCriteria 进行可能为空值的连接?
【发布时间】:2013-01-29 22:57:16
【问题描述】:

NHibernate 版本:3.3.1

原查询如下。

List<PostInstruction> instructions = PostInstruction.Query(
    Restrictions.Eq("Campaign", campaign),
    Restrictions.In("Status", new PostInstructionStatus[] { 
                PostInstructionStatus.Pending, 
                PostInstructionStatus.Finished 
                }),
    Restrictions.Or(
        Restrictions.Gt("DateCreated", DateTime.UtcNow - TimeSpan.FromMinutes(15)),
        Restrictions.IsNotNull("Post")
        )
    );

我们只将它用于计数功能,因此我将其转换为仅返回计数,但遇到了问题。我必须执行两个单独的查询才能考虑空 Post 值。有没有办法可以在单个查询中执行以下操作?

    public static int CountByCampaignCity(Campaign campaign, City city)
    {
        int finished, pending;

        using (ISession session = DataAccess.SessionFactory.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            try
            {
                Type objectType = typeof(PostInstruction);
                ICriteria criteria = session.CreateCriteria(objectType);

                criteria.Add(Restrictions.Eq("Campaign", campaign));
                criteria.Add(Restrictions.Eq("City", city));
                criteria.Add(Restrictions.Eq("Status", PostInstructionStatus.Finished));

                criteria.CreateCriteria("Post").Add(Restrictions.In("Status", new PostStatus[] { PostStatus.Pending, PostStatus.Live }));
                criteria.SetProjection(Projections.CountDistinct("Id"));

                finished = int.Parse(criteria.UniqueResult().ToString());
            }
            catch
            {
                if (transaction != null)
                    transaction.Rollback();

                throw;
            }
        }

        using (ISession session = DataAccess.SessionFactory.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            try
            {
                Type objectType = typeof(PostInstruction);
                ICriteria criteria = session.CreateCriteria(objectType);

                criteria.Add(Restrictions.Eq("Campaign", campaign));
                criteria.Add(Restrictions.Eq("City", city));
                criteria.Add(Restrictions.Eq("Post", null));
                criteria.Add(Restrictions.Eq("Status", PostInstructionStatus.Pending));
                criteria.Add(Restrictions.Gt("DateCreated", DateTime.UtcNow - TimeSpan.FromMinutes(15)));
                criteria.SetProjection(Projections.CountDistinct("Id"));

                pending = int.Parse(criteria.UniqueResult().ToString());
            }
            catch
            {
                if (transaction != null)
                    transaction.Rollback();

                throw;
            }
        }

        return pending + finished;
    }

【问题讨论】:

  • 您运行的是哪个版本的 nHibernate? ...只是出于好奇:为什么要在每次查询之前开始交易?
  • 使用 3.3.1,因为我只是复制粘贴代码以使其运行,同时我尝试在一个查询中找出如何做到这一点。
  • 我下面的回答对您有任何帮助吗?

标签: c# nhibernate


【解决方案1】:

使用 QueryOver,您应该能够执行以下操作:

var instructionsCount = session.QueryOver<PostInstruction>()
    .Select(Projections.Count<PostInstruction>(pi => pi.Id))
    .Where(pi => pi.Campaign == campaign && pi.City == city && (pi.Post == PostStatus.Pending || pi.Post == PostStatus.Live || pi.Post == null)); //Add your other conditions

Console.WriteLine(instructionsCount.SingleOrDefault<int>()); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    相关资源
    最近更新 更多