1

我正在查看以下示例代码以包含参考文档并避免往返。

var order = session.Query<Order>()
   .Customize(x => x.Include<Order>(o=>o.CustomerId)) // Load also the costumer
   .First();
var customer = session.Load<Customer>(order.CustomerId);

我的问题是 Raven 如何知道这o=>o.CustomerId意味着Customer文档/收藏?查询中从未Customer提供实体以获取Order实体。然而,Raven 声称第二个查询Customer可以针对缓存完成,无需任何网络行程。

如果是通过命名约定,这似乎是一个非常糟糕/脆弱/脆弱的约定,当我需要包含多个文档时会发生什么?

例如。一辆汽车是以 2 个名字购买的,所以我想链接回 2 个客户,主要和次要客户/司机。它们都存储在 Customer 集合中。

var sale = session.Query<Sale>()
   .Customize(x => x.Include<Sale>(o=>o.PrimaryCustomerId).Include<Sale>(o=>o.SecondaryCustomerId)) // Load also the costumer
   .First();
var primaryCustomer = session.Load<Customer>(order.PrimaryCustomerId);
var secondaryCustomer = session.Load<Customer>(order.SecondaryCustomerId);

如何在 1 次网络旅行中完成上述操作?Raven 怎么会知道这是对o=>o.PrimaryCustomerIdo=>o.SecondaryCustomerId一张表的引用,Customer因为显然属性名称和集合名称没有对齐?

4

1 回答 1

2

Raven 没有“桌子”的概念。它确实知道“集合”,但它们只是一种便利机制。在幕后,所有文档都存储在一个大数据库中。唯一构成“集合”的是每个文档都有一个Raven-Entity-Name元数据值。

您展示的两个示例都将导致一次往返(每个)。你的代码对我来说看起来很好。

我的问题是 Raven 如何知道这o=>o.CustomerId意味着客户文档/集合?查询中提供的实体 Customer 从未获得 Order 实体。

它不需要在查询中提供。只要存储在文档CustomerId字段中的数据Sale是完整的文档密钥,那么该文档就会返回给客户端并加载到会话中。

然而,Raven 声称第二次获取 Customer 的查询可以针对缓存完成,无需任何网络行程。

这是正确的。会话容器跟踪所有返回的文档——不仅仅是来自查询结果的文档。因此,稍后当您session.Load使用相同的文档密钥调用时,它已经在会话中拥有它,因此不需要返回服务器。

无论您是查询、加载还是包含 - 文档都不会反序列化为静态类型,直到您将其拉出会话。这就是您在调用中指定Customer类型的原因。session.Load<Customer>

如果是通过命名约定,这似乎是一个非常糟糕/脆弱/脆弱的约定……

不,它是存储在属性中的,它是文档键,例如"customers/123". 每个文档都可以通过其文档键来寻址,无论是否知道类的静态类型。

当我需要包含超过 1 个文档时会发生什么?

完全相同的事情。可以包含或加载到会话中的文档数量没有限制。但是,您应该确保在using语句中打开会话,以便正确处理它。会话是一个“工作单元容器”。

Raven 怎么会知道这是对o=>o.PrimaryCustomerIdo=>o.SecondaryCustomerId一张表 Customer 的引用,因为显然属性名称和集合名称没有对齐?

同样,字段的名称是什么并不重要。这些字段中的数据是否包含文档 ID 很重要,例如"customers/123". 如果您没有存储完整的字符串标识符,那么您将需要在 lambda 表达式中构建文档键。换句话说,如果Sale.CustomerId只包含数字123,那么您需要将它包含在 中.Include<Sale>(o=> "customers/" + o.CustomerId)

于 2013-08-21T03:03:57.520 回答