1

我正在尝试从 QueryOver 查询中返回多个实体。我在纯文本编辑器中编写此代码,因此可能存在语法错误,但它应该可以理解这个想法。

public class Product
{
    public virtual int ID { get; set; }
    public virtual string ProductName { get; set; }
    public virtual List<Category> Categories { get; set; }
    public virtual List<Inventory> Inventories { get; set; }
    ...
}

public class Category
{
    public virtual int ID { get; set; }
    public virtual string CategoryName { get; set; }
    public virtual string Style { get; set; }
    public virtual Product Product { get; set; }
    ...
}

public class Inventory
{
    public virtual int ID { get; set; }
    public virtual List<Discount> Discounts { get; set; }
    public virtual Product Product { get; set; }
    public virtual bool InStock { get; set; }
    ...
}

public class Discount
{
    public virtual int ID { get; set; }
    public virtual Inventory Inventory { get; set; }
    public virtual decimal DiscountAmount { get; set; }
    ...
}

现在我的目标是在单个查询中使用产品 ID 和其他几个选项来拉回类别、库存和折扣金额。我已经通过这个查询使用 HQL 来实现它:

var query = session.CreateQuery("select category, inventory, discount.DiscountAmount"
    + " from Product product"
    + " join product.Categories category"
    + " join product.Inventories inventory"
    + " left join inventory.Discounts discount"
    + " where product.ID = :productID"
    + " and category.Style = :style"
    + " and inventory.InStock = 1");

通过这个查询,我得到一个对象数组列表,每个对象数组都有一个 Category 实体、Inventory 实体和一个 DiscountAmount 小数。我的目标是使用 QueryOver 查询来执行相同的查询而不使用魔法字符串,但我无法让它工作。这是我到目前为止所尝试的:

Product productAlias = null;
Category categoryAlias = null;
...
var query = session.QueryOver<Product>(() => productAlias)
    .Where(() => productAlias.ID == productID)
    .JoinAlias(() => productAlias.Categories, () => categoryAlias)
    ...
    .Select(Projections.Property(() => categoryAlias.ID),
        Projections.Property(() => discountAlias.Inventory),
        Projections.Property(() => discount.DiscountAmount));

此查询仅拉回 Category 的 ID,虽然它确实拉回了完整的 Inventory 实体,但它使用完整的附加数据库查询来获取它。

    ...
    .Select(Projections.Property(() => categoryAlias),
        Projections.Property(() => inventoryAlias),
        Projections.Property(() => discountAlias.DiscountAmount));

此查询引发“无法解析属性:categoryAlias of : Product”的运行时异常。

    ...
    .Select(Projections.Property(() => categoryAlias.ID).WithAlias(() => ReturnClass.Category),
        Projections.Property(() => inventoryAlias.ID).WithAlias(() => ReturnClass.Inventory),
        Projections.Property(() => discountAlias.DiscountAmount).WithAlias(() => ReturnClass.DiscountAmount))
    .TransformUsing(Transformers.AliasToBean<ReturnClass>());

此查询引发“无法将 Int32 类型的对象转换为 Category 类型”的运行时异常。

    ...
    .Select(Projections.Property(() => categoryAlias.ID)
    .TransformUsing(Transformers.AliasToBean<Category>())

此查询返回默认类别实体。

那么有什么方法可以使用 QueryOver API 来模拟 HQL 查询,还是我唯一的选择是在 HQL 或进行多个查询之间进行选择?

编辑:为了更清楚,我真的想尽可能避免使用魔法字符串,所以我真的更喜欢强类型的 QueryOver 查询。目前我正在使用一个 QueryOver 查询,它返回 Category 和 Inventory 实体的 ID,然后分别查询它们,但由于无论如何我必须在第一个查询中点击这些表,我宁愿一次性返回它们。

编辑 2:我想要实现的确切 SQL 是

Select Category.ID, Category.CategoryName, Category.Style, (other Category columns),
Inventory.ID, Inventory.InStock, (other Inventory columns),
Discount.DiscountAmount
From Products as Product
Inner join Categories as Category ...
Where Product.ID = @productID
And Category.Style = @style
And ...
4

2 回答 2

0

因此,这是一个“渴望”为我的类别加载所有子类别的示例。迭代类别集合时没有 N+1。未来是这里的关键。

Category catalias = null;


        var subCategories =_session.QueryOver<Category>().JoinQueryOver(x => x.SubCategories, () => catalias, JoinType.LeftOuterJoin).
            Future<Category>();

        var categories = _session.QueryOver<Category>().Where(x => x.ParentCategoryId == null).Future<Category>();
于 2012-04-19T17:37:35.403 回答
0

我认为您应该使用 Fetch 而不是 JoinAlias:

.Fetch(product => product.Categories).Eager

并且不要使用 select: .List<Product>()// 然后通过 LINQ,您可以从 Product 获取类别和库存

于 2012-04-17T08:31:09.437 回答