1

我经常从我的同事那里听到“笛卡尔积”这个词,因为有一个领域模型在一个集合中包含一个集合并且渴望获取相同的集合。假设我有以下模型。

public class Order{
  List<Product> Products
}
public class Product{
  List<Units> Units
}

现在他们说,如果我尝试用产品和单位获取订单,我应该得到一个笛卡尔产品(又名重复..)。但是当我通过启用 ShowSql 对其进行测试时,我似乎没有得到任何重复。这是我的存储库类

    public List<Order> GetOrdersWithProductsAndUnits()
    {
        return GetSession().Query<Order>()
                           .FetchMany(order => order.Products)
                           .ThenFetch(product => product.Units)
                           .ToList();
    } 

这是启用 ShowSql 的 sql 输出。这似乎很好,并且与必要表上的连接一致。

select order0_.Id as Id8_0_, 
childstock1_.Id as Id23_1_,
childstock2_.Id as Id24_2_, 
order0_.CustomerName as Customer2_8_0_,  
order0_.City as City8_0_,
childstock1_.Size as Size23_1_,
childstock2_.Box as Box24_2_,
from Orders order0_  
left outer join Products childstock1_ on order0_.Id=childstock1_.OrderId  
left outer join Units childstock2_ on childstock1_.Id=childstock2_.ProductId

我的数据库中有 125 个订单,当我急切地获取带有产品和单位的订单时,我仍然得到 125 条记录。

List<Order> orders = repository.GetOrdersWithProductsAndUnits();
   Assert.That(orders.Count,Is.EqualTo(125));

此外,当我通过 Visual Studio 调试器检查时,我也没有在产品或单元级别的订单集合中找到任何重复项。

由于笛卡尔积导致重复,我期望数据库中的订单数与单位数一样多(接近 1000)。我是否遗漏了一些琐碎的事情,我对笛卡尔积的理解是否有偏差?或者我正在使用的查询 API 是否会自动解决笛卡尔积问题。

仅供参考:我也确定数据设置。我已经通过 Visual Studio 调试器进行了调试,我注意到具有多个产品的订单和具有多个单元的产品。

任何帮助/参考材料表示赞赏。

谢谢

4

2 回答 2

1

与其他查询类型(HQL、Criteria、QueryOver)相比,NHibernate 会自动丢弃 Linq 查询中的重复根实体。但是正如您在上一条评论中所说,您仍然会从数据库中获得那么多行,因此您的查询可能会很慢。

于 2013-05-16T05:59:03.560 回答
1

因此,您在此处遇到的笛卡尔积的问题是,您返回的行数比 SQL 中所需的行数要多,因为它为每个子对象返回具有完全相同数据的订单列的副本。因此,它实际上不是获得了 125 次订单,而是获得了 1000 次并在幕后“汇总”到您的订单对象中。每次重复的列是:order0_.Id, order0_.CustomerName, City8_0_

显然您需要重复 Order Id,因为它是 FK 并且存在于远程表中。但是想象一下,如果您的 Order 对象有更多的列,并且您在具有数百万子行的数据集上执行此操作。

使用像 HibernatingRhinos 这样的东西会极大地帮助你。我使用了他们的 EF 工具并避免了笛卡尔产品的许多问题,我不知道这些问题会在其他情况下发生。ORM 创建笛卡尔积的罪魁祸首通常是对对象树的急切加载/深度读取。使用基于视图的模型对象可以很容易地避免这种情况,而不是尝试通过在客户端代码中将对象链接在一起来构建结果集。

于 2017-08-03T21:34:32.183 回答