1

我使用 Breeze 在一个 asp.net mvc 项目上工作。

我有一个页面,我在其中显示有关传输的详细信息,并在其下方的表格中列出链接的传输。

考虑以下实体:

public class Transport
{
    [Key]
    public int Id { get; set; }
    public string TransportNumber { get; set; }
    public string Description { get; set; }
    public virtual List<LinkedTransport> LinkedTransports { get; set; }
    ...
}

public class LinkedTransport
{
    [Key, Column(Order = 0)]
    public int TransportId { get; set; }
    [Key, Column(Order = 1)]
    public int TransportRelatedId { get; set; }

    public virtual Transport Transport { get; set; }
    public virtual Transport TransportRelated { get; set; }
}

所以这两个实体允许我定义我的传输和(对于每个)链接的传输。

首先,我将我的(主要)传输加载到一个名为的 observable 中transport

var query = entityQuery.from('Transports')
                       .where('id', '==', transportId)
                       .expand("LinkedTransports.transportRelated");
query = query.using(breeze.FetchStrategy.FromServer);

请注意我在expand哪里检索链接的传输。

现在我有以下代码来显示我的传输和链接传输:

<div data-bind="with: transport()">
    <input type="text" data-bind="text: transportNumber"></input>
    <input type="text" data-bind="value: description"></input>       
    ...
    <table data-bind="foreach: linkedTransports">
        <tr>
            <td data-bind="text: transportRelated().transportNumber()"></td>
            <td data-bind="text: transportRelated().description()"></td>
        </tr> 
    </table>
</div>

到目前为止,一切都很好。我可以显示我的主要运输信息以及链接的运输信息。现在我需要让用户添加一些链接的传输。所以我有以下代码:

var createLinkedTransport = function (transpId, transpRelatedId) {

    var initialValues = ({
        transportId: transpId,
        transportRelatedId: transpRelatedId
    });

    manager.createEntity(entityNames.linkedTransport, initialValues);
};

在运行时,当我调用此函数时,我可以将链接传输添加到我的(主)传输。

我的问题:在我的 foreach 淘汰赛循环中未正确显示添加的元素。我看到表中添加了一个新行,但这一行是空的。我认为问题在于我没有expand关于我新添加的元素的任何信息,但我不知道如何继续。

知道如何进行吗?


更新

需要明确的是,当我将linkedTransport 添加到我的传输时,在添加之后(并且没有重新加载页面)我无法读取目标(*)linkedTransport 的属性。但是如果我保存更改并重新加载我的页面,那么我可以读取目标链接传输的属性。

当我说“目标链接传输”时,我的意思是由我的 TransportRelatedId (>> public virtual Transport TransportRelated) 引用的传输。

因此,如果我立即将linkedTransport #123添加到传输#456 THEN(无需重新加载页面),我将无法显示Description#123 的属性。

<div data-bind="with: transport()">
    ...
    <div data-bind="foreach: linkedTransports">
        <label data-bind="text: transportRelated().description()"></label>
    </div>
</div>

希望我很清楚。


更新 2

正如 Ward 所建议的,我在添加后立即设置断点linkedTransports并检查transport().linkedTransports(). 以下是结果:

在此处输入图像描述

  • transport().linkedTransports()[0].transport() >> 属性在那里
  • 运输().linkedTransports()[0].transportId() >> 1
  • transport().linkedTransports()[0].transportNumber >> '123456' (“虚拟”属性,没有帮助)
  • transport().linkedTransports()[0].transportRelated() >> null
  • transport().linkedTransports()[0].transportRelatedId() >> 5(linkedTransport的id)

所以我的问题是它transportRelated()是空的。


更新 3

最后我让它工作了。在添加时将添加的(引用的)元素保存在缓存中是很重要的。对于我的情况,我会做类似的事情:

ctxTransport.getTransportById(5, obs);
ctxTransport.createLinkedTransport(1, 5);

所以在调用之前,createLinkedTransportgetTransportById用第 5 个 id(linkedTransport 的 id)调用。

另一件重要的事情是我们如何在页面上显示linkedTransports:

<div data-bind="foreach: linkedTransports">                        
    <span class="input-control text">
        <!-- ko with: transportRelated -->
        <a href="#" class="fg-color-darken" data-bind="attr: { href: '#/generalTransport/' + id(), title: 'Cliquez pour ouvrir ce transport' }, text: transportNumber"></a>
        <!-- /ko -->
        <i class="icon-remove btn" data-bind="click: $root.removeLinkedTransport" style="cursor:pointer;"/>
    </span>
</div>

注意ko with: transportRelated后面的<a href="#" data-bind="text: id()"。起初我做错了<a href="#" data-bind="text: transportRelated().id()"。我们不能这样进行。

4

1 回答 1

0

更新的答案

简而言之:相关的传输实体没有出现,因为它不在缓存中。

B 先生拥有相关实体的 ID,并在创建新的传输链路实体时使用该 ID。但是那个 id 引用了一个不在缓存中的实体。因此,相关传输实体的导航属性返回... null。

Breeze 导航属性不会延迟加载(就像 EF 等服务器端 ORM 可能会做的那样)。您必须确保引用的实体在缓存中。

这是一个设计选择,而不是一个遗漏。根据我们的经验,延迟加载会导致误用,从而导致归咎于框架的性能问题。我们决定绕过这个特殊的麻烦.. 至少现在是这样。

有关更多信息,请参阅评论。

也许同样重要……看看我们是如何诊断问题的。在那里学到了很好的教训。

原来的“错误”答案

[这个答案原来是“错误的”,但它导致了“正确”的答案。保持连续性。]

EF 如何处理您的 LinkedTransport 实体?看起来它缺乏自己的数据属性;它只有相关实体的外键。难道是EF把LinkedTransport看作是多对多关联的联结表。

您可能知道,Breeze 不(目前……也不会很快)支持多对多。如果你给这个表一个数据属性会发生什么……甚至是一个虚拟的数据属性,比如布尔值?这将迫使 EF 将其视为自己的实体类型......使用复合键。Northwind 中的 OrderDetail 具有相同的结构:复合键(订单、产品)和小负载(数量、价格)。

可能还有另一种方法可以告诉 EF 在不添加虚拟属性的情况下不要将其视为多对多。我只是不记得那是什么。

于 2013-08-23T00:58:10.330 回答