2013-10-06 128 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)) 
      );