NHibernate 搜索多对多关系上的某些属性

本文关键字:属性 关系 搜索 NHibernate | 更新日期: 2023-09-27 18:34:09

我有两个类ProductProductDetail(见下文)

我想在同一个查询中搜索Product对象中的CodeProductDetail中的Name。结果应为Product列表。

我试过这个:

var search = "stringToSearch";
var list = _session.QueryOver<Product>()
    .Fetch(x => x.ProductDetails).Eager.Future<Product>()
    .Where(
        x => x.Code.StartsWith(search) || 
        x.ProductDetails.First().Name.StartsWith(search))
    .ToList();

当搜索与Code属性和ProductDetail的第一条记录的Name匹配时,查询会为我提供正确的结果,但我想搜索ProductDetails的所有记录.

我该怎么做?

谢谢

public class Product
{
    public virtual int Id { get; set; }
    public virtual string Code { get; set; }
    public virtual IList<ProductDetail> ProductDetails { get; set; }
}
public class ProductDetail
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual IList<Product> ProductDetails { get; set; }
}
The mapping :
public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Table("Product");
        Id(x => x.Id).GeneratedBy.Native();
        Map(x => x.Code).Length(20).Unique().Not.Nullable();
        HasManyToMany(x => x.ProductDetails)
           .Cascade.All()
           .Table("ProductsProductsDetails");
    }
}
public class ProductDetailMap : ClassMap<ProductDetail>
{
    public ProductDetailMap()
    {
        Table("ProductDetail");
        Id(x => x.Id).GeneratedBy.Native();
        Map(x => x.Name).Not.Nullable().Length(50);
        Map(x => x.Description).Length(200);
        HasManyToMany(x => x.Products)
            .Cascade.All()
            .Inverse()
            .Table("ProductsProductsDetails");
    }
}

NHibernate 搜索多对多关系上的某些属性

若要查询这两个实体,只需使用别名联接它们,然后使用这些别名查询属性

// alias definition
Product productAlias = null;
ProductDetail detailAlias = null;
var list = session.QueryOver<Product>(() => productAlias)
    .JoinAlias(() => productAlias.ProductDetails, () => detailAlias)
    .Where(() => productAlias.Code.StartsWith(search))
    .And(() => detailAlias.Name.StartsWith(search))
    .List();

不幸的是,nHibernate不允许在此语法中使用string.StartsWith,因此您必须优化查询以使用.WhereRestrictionOnIsLike,如下所示:

var list = session.QueryOver<Product>(() => productAlias)
    .JoinAlias(() => productAlias.ProductDetails, () => detailAlias)
    .WhereRestrictionOn(() => productAlias.Code).IsLike(search, MatchMode.Start)
    .AndRestrictionOn(() => detailAlias.Name).IsLike(search, MatchMode.Start)
    .List();

编辑:刚刚发现你想要一个OR查询,为此我们必须结合where语句中的限制,例如:

var listWithOr = session.QueryOver<Product>(() => productAlias)
   .JoinAlias(() => productAlias.ProductDetails, () => detailAlias)
   .Where(Restrictions.On(() => productAlias.Code).IsLike(search, MatchMode.Start)
        || Restrictions.On(() => detailAlias.Name).IsLike(search, MatchMode.Start))
   .List();

希望这有帮助

编辑2:上面的查询不会给你一个明显的结果,有些产品可能会多次出现在列表中,如果需要,你必须把它变成一个不同的结果......

相同的查询(已经具有不同的结果)可以通过一个简单的NHibernate.Linq语句来实现:

var list2 = session.Query<Product>()
            .Where(prod => prod.Code.StartsWith(search) ||
                prod.ProductDetails.Any(detail => detail.Name.StartsWith(search))
            );