2013-10-06 80 views
2

我有两个类ProductProductDetail一些属性(见下文)NHibernate的搜索上许多一对多的关系

我想进行搜索,在相同的查询,对CodeProduct对象和NameProductDetail。结果应该是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"); 
    } 
} 

回答

2

要查询两个实体,你可以简单地用别名加入他们,然后使用这些别名来查询性能

// 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(); 

:编辑:刚刚找到你想要的或查询,要做到这一点,我们必须将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(); 

希望这有助于

:EDIT2: 以上查询不会给你一个不同的结果,有些产品可能会出现在列表中多次,如果需要,你将不得不作出不同的结果...

用简单的NHibernate.Linq声明可以实现相同的查询(具有不同的结果):

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