代码之家  ›  专栏  ›  技术社区  ›  Barbaros Alp

使用nhibernate标准API查询集合?

  •  4
  • Barbaros Alp  · 技术社区  · 17 年前

    我有一个“不动产”实体,这个实体有一个集合“不动产特征”(类型:不动产特征),而不动产特征有一个属性“myFeatureValue”。

    注意:这些是问题的有限属性。所有实体都有一个ID和所有必要的等

    房地产

    IList<EstateFeature> EstateFeatures;
    

    遗产特征

    FeatureValue MyFeatureValue;
    

    特征值

    public virtual long Id;
    

    我想买具有给定特征值的房地产。

    DetachedCriteria query = DetachedCriteria.For<Estate>();
    Conjunction and = new Conjuction();
    foreach (var id in idCollection)
       and.Add(Expression.Eq("MyFeatureValue.Id",id);
    
    query
         .CreateCriteria("EstateFeatures")
         .Add(and);
    IList<Estate> estates = query.GetExecutableCriteria(session).List<Estate>();
    

    这个查询没有返回任何内容,我是否做错了什么?

    谢谢

    7 回复  |  直到 9 年前
        1
  •  2
  •   jishi    17 年前

    您需要确保为您想要的遗产拥有的每个功能加入一次MyFeatureValue。

    一种方法是为每个迭代调用.createAalias,给它一个唯一的别名,然后添加表达式“aliax.id”

    foreach (var id in idCollection)
    {
       query = query.CreateAlias("MyFeatureValue", "feature" + id)
                    .Add(Expression.Eq("feature" + id + ".Id",id);
    
    
    }
    

    我真的不记得语法是如何发展的,把它写在我的脑子里,也不确定是否需要重新声明查询:)

    但是,我认为这会让你开始。

    编辑:由于条件API中的错误限制您使用CreateAlias或CreateCriteria多次关联集合,因此需要使用HQL。

    http://derek-says.blogspot.com/2008/06/duplicate-association-path-bug-in.html

    (冬眠也有同样的问题)

    select e   
    FROM Estate AS e
    INNER JOIN e.MyFeatureValue AS fv1
    INNER JOIN e.MyFeatureValue AS fv2
    WHERE fv1.Id = 3
       AND fv2.Id = 13
    
    

    您需要动态构建HQL,以便别名变得唯一(fv1、fv2、fvx…)

        2
  •  8
  •   Remmus    17 年前

    如果我理解正确的话,我想这样的事情可能会奏效。

    CreateCriteria(typeof(Estate))
         .CreateAlias("EstateFeatures", "estatefeature")
         .Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
         .List<Estate>();
    
        3
  •  2
  •   Frederik Gheysels    17 年前

    nhibernate为您生成了什么查询?您可以使用show_sql config属性来检查这一点。

    正如我看到的您的查询,您正在尝试获取具有给定功能集的所有地产。 我认为,这将生成一个看起来像

    SELECT ....
    FROM Estates
    INNER JOIN Features
    WHERE Feature.Id = 1 AND Feature.Id = 2 ...
    

    如果要检索包含所有指定功能的所有地产,我认为必须使用分离,以便nhibernate检索至少具有其中一个功能的所有地产。 然后,在您的客户代码中,您将检查您的“客户代码”中的每一个地产,以便最终得到具有所有功能的地产。
    我不知道是否有一个有效的方法让NHibernate处理这个…

        4
  •  1
  •   RKitson    17 年前

    代码看起来像是在传递一个特性值列表,并需要一个具有所有这些特性的列表。如果是这样的话,我将查看正在生成的SQL,并对数据库运行它,以查看您是否应该返回任何内容。

    否则,如果您正在寻找一个具有您要传递的任何特性的列表,那么您应该使用分离而不是连接。

        5
  •  0
  •   Barbaros Alp    17 年前
        exec sp_executesql N'SELECT TOP 3 id11_1_, Address11_1_, Title11_1_, Descript4_11_1_, 
        Price11_1_, Discount11_1_, ForBankL7_11_1_, AddDate11_1_, LastUpdate11_1_, 
    IsVisible11_1_, ViewCount11_1_, SaleOrRent11_1_, LocationId11_1_, StaffId11_1_, 
    CategoryId11_1_, id27_0_, EstateId27_0_, FeatureV3_27_0_ FROM (SELECT ROW_NUMBER() 
    OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id11_1_, query.Address11_1_, 
    query.Title11_1_, query.Descript4_11_1_, query.Price11_1_, query.Discount11_1_, 
    query.ForBankL7_11_1_, query.AddDate11_1_, query.LastUpdate11_1_, query.IsVisible11_1_, 
    query.ViewCount11_1_, query.SaleOrRent11_1_, query.LocationId11_1_, query.StaffId11_1_, 
    query.CategoryId11_1_, query.id27_0_, query.EstateId27_0_, query.FeatureV3_27_0_, 
    query.__hibernate_sort_expr_0__ FROM (SELECT this_.id as id11_1_, this_.Address as 
    Address11_1_, this_.Title as Title11_1_, this_.Description as Descript4_11_1_, this_.Price 
    as Price11_1_, this_.Discount as Discount11_1_, this_.ForBankLoan as ForBankL7_11_1_, 
    this_.AddDate as AddDate11_1_, this_.LastUpdate as LastUpdate11_1_, this_.IsVisible as 
    IsVisible11_1_, this_.ViewCount as ViewCount11_1_, this_.SaleOrRent as SaleOrRent11_1_, 
    this_.LocationId as LocationId11_1_, this_.StaffId as StaffId11_1_, this_.CategoryId as 
    CategoryId11_1_, estatefeat1_.id as id27_0_, estatefeat1_.EstateId as EstateId27_0_, 
    estatefeat1_.FeatureValueId as FeatureV3_27_0_, CURRENT_TIMESTAMP as 
    __hibernate_sort_expr_0__ FROM Estate this_ inner join EstateFeature estatefeat1_ on 
    this_.id=estatefeat1_.EstateId WHERE this_.CategoryId = @p0 and 
    (estatefeat1_.FeatureValueId = @p1 and estatefeat1_.FeatureValueId = @p2 and 
    estatefeat1_.FeatureValueId = @p3 and estatefeat1_.FeatureValueId = @p4 and 
    estatefeat1_.FeatureValueId = @p5 and estatefeat1_.FeatureValueId = @p6 and 
    estatefeat1_.FeatureValueId = @p7)) query ) page WHERE page.row > 0 ORDER BY 
    __hibernate_sort_expr_0__',N'@p0 bigint,@p1 bigint,@p2 bigint,@p3 bigint,@p4 bigint,@p5 
    bigint,@p6 bigint,@p7 bigint',@p0=3,@p1=7,@p2=8,@p3=9,@p4=10,@p5=11,@p6=12,@p7=16
    
        6
  •  0
  •   yfeldblum    17 年前

    看起来像你想要的 or ( Disjunction )而不是 and ( Conjunction )现在,你正在寻找 EstateFeature s对象,使每个对象具有多个不同的 Id S,这似乎不是你想要的。

    var or = new Disjunction();
    foreach(var id in idCollection)
        or.Add(Expression.Eq("MyFeatureValue.Id", id);
    
    var query = DetachedCriteria.For<Estate>();
    query
        .CreateCriteria("EstateFeatures")
        .Add(and);
    var estates = query.GetExecutableCriteria(session).List<Estate>();
    
        7
  •  0
  •   krlzlx    9 年前

    我也试过,但结果是一样的:

    DetachedCriteria features = DetachedCriteria.For<FeatureValue>();
    features.SetProjection(Projections.Property("Id"));
    features.Add(Property.ForName("Id").EqProperty("value.Id"));
    
    var and = new Conjunction();
    
    foreach (var l in FeatureIdCollection)
        and.Add(Expression.Eq("Id", l));
    
    features.Add(and);
    
    query.CreateCriteria("EstateFeatures")
         .CreateCriteria("MyFeatureValue","value")
         .Add(Subqueries.Exists(features));
    
    推荐文章