nHibernate - 查询多对多

时间:2016-02-17 08:03:22

标签: c# nhibernate

我无法查询具有多对多关系的对象。

我的模特看起来像这样。因此,m-n关系将自行解决。

ProductionOrder           Product              ProductPart
   +-----+                +-----+                +-----+
   |     |                |     | 1------------n |     |    
   |     |  n --------- 1 |     |                |     |
   |     |                |     | n------------1 |     |
   +-----+                +-----+                +-----+

一种产品可以是许多产品的一部分,一种产品可以有许多部件 我现在尝试检索给定产品属于的ProductionOrder 要生产的产品。

在简单的SQL中,这非常简单并且工作正常

SELECT * FROM ProductionOrder po
INNER JOIN Product p 
ON po.ProductId = p.Id
INNER JOIN ProductPart pp
ON p.Id = pp.ContainingProductId
WHERE pp.PartProductId = 403

但是我没能在nHibernate中做到这一点。

首先尝试:
我尝试按照查询返回任何内容:

private decimal GetNeededForProduction(Product product)
{
    //Retrieve all ProductionOrders where Product is a Part
    var productionOrders = Session.Query<ProductionOrder>()
        .Where(x => x.Product.Parts.Select(p => p.PartProduct.Id).Contains(product.Id))
        .Fetch(x => x.Product).ThenFetch(x => x.Parts)
        .ToList();
}

第二次尝试:
我还发现WhereRestriction有一个方法IsIn,但恰恰相反。

var test = Session.QueryOver<ProductionOrder>()
                .WhereRestrictionOn(x => x.Product.Parts.Select(p => p.PartProduct.Id)).IsIn(new long[] {product.Id});

并且还会抛出异常

InvalidOperationException was unhandled by user code
variable 'x' of type 'Pmc.Model.Production.ProductionOrder' referenced from scope '', but it is not defined

第三次尝试:

var result = Session.QueryOver<ProductionOrder>()
            .Inner.JoinQueryOver<ProductPart>(x => x.Product.Parts)
            .Where(pp => pp.PartProduct.Id == product.Id).List<ProductionOrder>();

抛出

{"The multi-part identifier \"productpar1_.PartProductId\" could not be bound."}

提前致谢

Edit1 - 添加了c#-model-classes和映射

public class Product 
{
    //More properties
    public virtual IList<ProductPart> Parts { get; set; }
}

public class ProductPart : IHaveId
{
    /// <summary> parent </summary>
    public virtual Product ContainingProduct { get; set; }
    /// <summary> child </summary>
    public virtual Product PartProduct { get; set; }

    //More properties      
}

映射

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Id(x => x.Id);
        HasMany(x => x.Parts).KeyColumn("ContainingProductId").Inverse().Cascade.DeleteOrphan().BatchSize(20);
    }
}

public class ProductPartMap : ClassMap<ProductPart>
{
    public ProductPartMap()
    {
        Id(x => x.Id);
        References(x => x.ContainingProduct);
        References(x => x.PartProduct);
    }
}

1 个答案:

答案 0 :(得分:2)

查询应为:

var result = Session.QueryOver<ProductionOrder>()
    .Inner.JoinQueryOver<Product>(x => x.Product)
    .Inner.JoinQueryOver<ProductPart>(x => x.Parts)
    .Where(x => x.PartProduct.Id == product.Id)
    .List();

请注意,在NHibernate中,“自然连接条件”(主键/外键)由JoinQueryOver隐式赋予,因此您不必重复它们。