2

私は2つのクラスを持っていますProductProductDetail以下を参照)

Code同じクエリで、 in Productobject と on Nameinで検索したいと思いますProductDetail。結果はリストになるはず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プロパティ および と一致すると、クエリは正しい結果を返しますが、 のすべてのレコードを検索したいと思います。NameProductDetailProductDetails

これどうやってするの ?

ありがとう、

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");
    }
}
4

1 に答える 1

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

string.StartsWith残念ながら、nHibernate ではこの構文を使用できないため、使用するクエリを次.WhereRestrictionOnのように調整する必要がありますIsLike

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

お役に立てれば

:Edit2: 上記のクエリでは明確な結果が得られません。一部の製品はリストに複数回出現する可能性があります。必要に応じて、明確な結果にする必要があります...

NHibernate.Linq同じクエリ (すでに異なる結果) は、単純なステートメントで実現できます。

var list2 = session.Query<Product>()
            .Where(prod => prod.Code.StartsWith(search) ||
                prod.ProductDetails.Any(detail => detail.Name.StartsWith(search))
            );
于 2013-10-06T09:41:24.547 に答える