【问题标题】:CreateCriteria over a collection of simple types基于简单类型集合的 CreateCriteria
【发布时间】:2014-11-05 06:08:43
【问题描述】:

如何使用CreateCriteria 查询简单类型的集合?

例如,我有 1 个班级

public class Test
{
    public virtual Guid Id { get; set; }

    private ICollection<int> _values = new HashedSet<int>();        
    public virtual ICollection<int> Values
    {
        get { return _values; }
    }
}

还有 2 个表来支持它:

  • 仅使用 1 列进行测试:Id
  • 具有 2 列的值:TestId 和 Value

我的目标是使用CreateCriteria重写以下查询:

select * from test t
inner join values v on v.TestId = t.Id
where v.Value = 10

我试过这个:

Session.CreateCriteria<Test>("test")
  .CreateAlias("test.Values", "values")
  .Add(Restrictions.Eq("values", 10))
  .List();

就像我用一组对象做的那样,显然失败了。加入是正确的,但如何添加限制?

【问题讨论】:

    标签: c# sql nhibernate nhibernate-criteria


    【解决方案1】:

    尽管有问题,我还是建议使用IList&lt;ValueEntity&gt; 而不是IList&lt;int&gt;

    好吧,只有当包含值 ([dbo].[values]) 的表可以有自己的代理 ID 列时,这才有效。 IE。通过这些列:IDTestIdValue 我们可以引入新实体 ValueEntity 并将其映射为一级公民。然后查询它会变得更加简单,包括子查询..

    但我知道这里不是问题。

    而事实上,有一个解决方案,上面的问题有答案。但是,请至少尝试考虑上述建议...

    IList&lt;int&gt;集合查询的NHibernate解决方案是:

    Session.CreateCriteria<Test>("test")
      .CreateAlias("test.Values", "values")
      // we add magic keyword ".elements" here
      .Add(Restrictions.Eq("values.elements", 10))
      .List();
    

    查看“.elements”,它的记录有点不正确here。还提供了这个类似问题的答案:NHibernate How do I query against an IList<string> property?

    【讨论】:

    • 非常感谢,这很狡猾:)
    【解决方案2】:

    elements 的方法对我不起作用。不知何故,NHibernate 选择了错误的别名...... 所以从

    CurrentSession.CreateCriteria<EmployeeIntranetSettings>("settings")
        .CreateAlias("settings.DefaultLMSOwnershipCapacities", "capacity")
        .Add(Restrictions.Eq("capacity.elements", OwnershipCapacity.VehicleFinance))
        .SetProjection(Projections.Id())
        .List<Guid>();
    

    它创造了

    SELECT this_.Id as y0_ 
    FROM intranet.sfEmployeeIntranetSettings this_ 
    inner join contact.sfEmployeeDefaultLMSOwnershipCapacities defaultlms3_ on this_.Id=defaultlms3_.EmployeeId
    WHERE capacity1_.Capacity = @p0
    

    如您所见 - 容量的别名不同。

    所以我会支持关于 ValueType 实体的建议,尽管它可能违反 DDD。作为具有当前架构的工作解决方案(至少对我而言):

    CurrentSession.CreateCriteria<Employee>("employee")
        .Add(Expression.Sql(
            "Exists (select top 1 null from contact.sfEmployeeDefaultLMSOwnershipCapacities dc where dc.EmployeeId = {alias}.Id and dc.Capacity = ?)", 
            "'" + OwnershipCapacity.VehicleFinance + "'", 
            NHibernateUtil.String))
        .SetProjection(Projections.Id())
        .List<Guid>();
    

    这里很少有兴趣点:

    • 在我的情况下,{alias} 将导致根实体别名(员工)。很遗憾,您不能使用任何其他别名;
    • 对于 sql 查询,我使用了 value - 它将替换 ?,但由于它是一个字符串 - 我不得不用 "'" 转义它。

    【讨论】:

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