我在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; }
}
所以这两个实体允许我定义我的传输和(对于每个)链接的传输。
首先,我将我的(主)传输加载到名为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的属性。但是,如果我saveChanges并重新加载我的页面,那么我可以读取目标linkedTransport的属性。
当我说'targetted linkedTransport'时,我指的是我的TransportRelatedId(&gt;&gt;&gt; public virtual Transport TransportRelated
)引用的传输。
因此,如果我立即将linkedTransport #123 添加到传输#456 那么(无需重新加载页面)我无法显示该属性的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()
。以下是结果:
所以我的问题是transportRelated()
为空。
更新3
最后我开始工作了。添加(添加)时,在缓存中添加(引用)元素非常重要。对于我的情况,我做了类似的事情:
ctxTransport.getTransportById(5, obs);
ctxTransport.createLinkedTransport(1, 5);
所以在调用createLinkedTransport
之前,我使用第5个ID(linkedTransport的id)调用getTransportById
。
重要的是我们如何在页面上显示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()"
。我们不能这样做。
答案 0 :(得分:0)
缺点:相关的传输实体没有显示,因为它不在缓存中。
先生。 B具有相关实体的ID,并在创建新的传输链接实体时使用该ID。但是该id指的是不在缓存中的实体。因此,相关传输实体的导航属性返回... null。
Breeze导航属性不会延迟加载(作为服务器端的ORM,如EF可能会这样做)。您必须确保引用的实体位于缓存中。
这是一个设计选择,而不是遗漏。根据我们的经验,延迟加载会导致滥用,从而导致出现在框架上的性能问题。我们决定绕过这个特别的麻烦..至少现在。
有关详细信息,请参阅评论。
也许同样重要......看看我们如何诊断出这个问题。在那里学到了很好的经验教训。
[这个答案结果是“错误的”,但它导致了“正确”的答案。保留连续性。]
EF如何处理您的LinkedTransport实体?看起来它缺乏自己的数据属性;它只有相关实体的外键。可能是EF认为LinkedTransport是多对多关联的联结表。
正如你可能知道的那样,Breeze不会(但不会很快)支持很多人。如果你给这个表一个数据属性...甚至一个虚拟数据属性,如布尔值会发生什么?这将迫使EF将其视为自己的实体类型......使用复合键。 Northwind的OrderDetail具有相同的结构:复合键(订单,产品)和小工资(数量,价格)。
可能有另一种方法告诉EF不要在没有添加虚拟属性的情况下将其视为多对多。我只是不记得那是什么。