【发布时间】:2013-01-13 14:23:14
【问题描述】:
嗯。对我来说似乎是错误的。我有一个轻而易举的查询:
var query = new breeze.EntityQuery()
.from("AllGames")
.expand("Sets, MVP, TeamerMVP.Person")
.orderBy("GameDateTime desc");
(每场比赛可以没有或有很多 TeamerMVP 记录,并且与 person 表存在一对一的关系,因此 TeamerMVP.Person 的扩展语句,因此我可以亲自直接访问“Name”属性。这行得通完美在直接一对一相关的MVP中(每场比赛只能有一个)
一切似乎都很好 - 相关实体已加载,我也可以访问原型函数中的子实体。但是,我尝试在与子实体的 html 绑定中做很多事情时遇到问题,并且在检查 chrome 的控制台时,似乎可能是因为子实体与父实体不同,没有被声明为dependentobservable,它们只是普通的“对象” ”。
viewmodel defines parent as: games = ko.observableArray([])
控制台评估:
$data
Object
games: Object[0]
_latestValue: Array[7]
0: Game
1: Game
2: Game
>GameDateTime: function dependentObservable() {
>HomeGame: function dependentObservable() {
>ID: function dependentObservable() {
>LeagueGame: function dependentObservable() {
>MVP: function dependentObservable() {
>MVP_PersonID: function dependentObservable() {
>NLorRL: "<strong>NL</strong> (A)"
>Opponent: function dependentObservable() {
>Sets: Object[0]
>TeamerMVP: Object[0]
在展开的节点中,您可以看到父实体级属性(GameDateTime、HomeGame 等)被创建为依赖可观察对象,但子实体(Sets、TeamerMVP)不是,我猜这就是为什么我'我在 html 模板绑定中遇到了一些问题,比如“foreach”,因为淘汰赛似乎根本看不到那些子实体。
我有什么遗漏吗?我是否应该在视图模型中创建“games.Sets = ko.observableArray([])”声明,以便在创建子实体时充当子实体的容器?
返回的json数据如下:
TeamerMVP: [{$id:20, $type:lbD.model.TeamerMVP, lbD.model, GameID:3, PersonID:4,…}]
0: {$id:20, $type:lbD.model.TeamerMVP, lbD.model, GameID:3, PersonID:4,…}
$id: "20"
$type: "lbD.model.TeamerMVP, lbD.model"
GameID: 3
Person: {$id:21, $type:lbD.model.Person, lbD.model, ID:4, Name:Mike Connor, isAdmin:false,…}
PersonID: 4
并且很容易在相关的 Person 表中看到“Name”属性。
编辑添加: 只是“TeamerMVP”关系比较麻烦。刚刚设法在“Sets”实体上使用“forEach”做一些事情,所以它工作正常,即使它不是一个依赖可观察的......我很困惑。
针对 Ward 的问题进一步编辑:
在请求的断点处,我看到了这些列表:
breezeConfig.manager.metadataStore._structuralTypeMap
Object
>Game:#lbD.model: ctor
>GameSet:#lbD.model: ctor
>Person:#lbD.model: ctor
>TeamerMVP:#lbD.model: ctor
>Venue:#lbD.model: ctor
>__proto__: Object
这些是我的(简单)数据库中的具体表名。如果我展开“GameSet”,那么其中一个属性是:defaultResourceName:“Sets”,它是导航属性名称(在模型中定义为“Public Overridable Property Sets() As ICollection(Of GameSet)”)。
啊...刚刚扩展了“TeamerMVP”,它的默认资源名称是“TeamerMVPs”,这是一个很小但微妙的区别!我不记得在任何地方都定义了结尾带有“s”的版本,并且快速搜索该项目没有发现任何结果。好奇的。也许这就是问题所在,我现在将快速玩一下 html 绑定。
编辑 3:HTML 绑定信息
不,根本不打球……
我有这个模板:
<script type="text/html" id="TeamerMVPTemplate">
<div>Teamer MVP(s): </div>
<li data-bind="text: Person().Name"></li>
</script>
嵌入在另一个模板(主要的“foreach:游戏”模板)中,这是它被引用的地方:
<span class="fixtureBoxLine" data-bind="template: { name: 'setScoresTemplate', foreach: Sets }"></span>
<span class="fixtureBoxLine" data-bind="template: { name: 'TeamerMVPTemplate', foreach: TeamerMVPs }"></span>
...它只是默默地打破。没有错误消息,但处理在第一个游戏的第一个循环时停止。其上方的“foreach: Sets”模板完美运行。
如果我在上面的绑定声明中将“foreach: TeamerMVPs”改回“foreach: TeamerMVP”,所有游戏都会被处理,但 TeamerMVP 的模板中没有显示任何内容,所以我猜“TeamerMVPs”是正确的实体引用并且有我尝试访问它的方式发生了一些奇怪的事情。 “Person().Name”是模板中的正确绑定吗?
=============================================
编辑 4:模型说明
manager.metadataStore.getEntityType('Game').navigationProperties 返回 4 个导航属性。这是正确的,应该有一个 0 对多个“Sets”的集合,一个 0 对多个“TeamerMVP”的集合,一个 0 对一的“MVP”和一个 0 对一的“Venue”。所有人都在场。
可以只有一个(或没有)MVP,但从 0 到多个 TeamerMVP 是完全正确的。这种关系的建立方式与“Sets”关系的工作方式完全相同。唯一的细微差别是“TeamerMVP”tavle 本身与“Person”表具有 1 对 1 的关系,因为任何 TeamerMVP 都必须是有效的人。这就是为什么我的微风查询定义了一个引用“TeamerMVP.Person”的“扩展”,这似乎可以正常工作,因为返回的 json 数据完全符合我的预期。在原始 json 中,导航属性被称为“TeamerMVP”,只有在“structuraltypemap”中 defaultResourceName 被称为“TeamerMVPs”。
如果我将 html 绑定保留为“forEach TeamerMVP”,则所有游戏都将返回并按预期绑定到“foreach games”父模板,但没有数据绑定到 TeamerMVP 模板,控制台中也不会显示任何错误。如果我将绑定更改为“foreach TeamerMVPs”,则只返回一场比赛,然后在发生绑定并显示数据时停止处理。但是,控制台中不会显示任何错误。
似乎微风在内部将导航属性创建为“TeamerMVP”,但 json 正在返回“TeamerMVP”,也许这种差异是绑定似乎有效但没有绑定数据的原因?远远超出了我目前的理解范围!
================================================ ===================
编辑5:添加模型信息
游戏模型
Public Class Game
Public Property ID() As Integer
Public Property GameDateTime() As System.DateTime
Public Property Opponent() As String
Public Property HomeGame() As Boolean
Public Property LeagueGame() As Boolean
Public Property MVP_PersonID() As Nullable(Of Integer)
Public Property VenueID() As Nullable(Of Integer)
Public Property isNL() As Boolean
Public Overridable Property Sets() As ICollection(Of GameSet)
Public Overridable Property MVP() As Person
Public Overridable Property TeamerMVP() As ICollection(Of TeamerMVP)
Public Overridable Property Venue() As Venue
End Class
TeamerMVP 模型
Public Class TeamerMVP
Public Property GameID() As Integer
Public Property PersonID() As Integer
Public Overridable Property Person() As Person
End Class
人物模型
Public Class Person
Public Property ID() As Integer
Public Property Name() As String
Public Property isAdmin() As Boolean
Public Property email() As String
Public Property type() As String
Public Property Image() As String
Public Property thumbImage() As String
Public Property backImage1() As String
Public Property backImage2 As String
Public Property Height() As String
Public Property YearStarted() As String
Public Property Position() As String
Public Property PreviousClubs() As String
Public Property ShirtNumber() As String
Public Property isNL() As Boolean
Public Overridable Property Games_MVP() As ICollection(Of Game)
Public Overridable Property Games_TeamerMVP() As ICollection(Of Game)
End Class
游戏集模型
Public Class GameSet
Public Property ID() As Integer
Public Property GameID() As Integer
Public Property SetNo() As Integer
Public Property ourScore() As Integer
Public Property theirScore() As Integer
Public Overridable Property Game() As Game
End Class
在控制台的成功断点处使用breezeConfig.manager.getEntities('TeamerMVP') 确实会显示大量“TeamerMVP”实体。网络资源选项卡也显示了原始返回数据中“TeamerMVP”的正确相关实体。
但是,在控制台中的成功断点处运行data.results[0].TeamerMVP() 仍然没有返回任何内容:
data.results[0].TeamerMVP()
>[]
data.results[2].TeamerMVP()
>[]
上面的第一个是正确的,第一个返回的游戏还没有关联的“TeamerMVP”实体,但是序列中的第三个游戏确实有关联的实体,如返回的原始 json 数据所示:
TeamerMVP: [{$id:4, $type:lbD.model.TeamerMVP, lbD.model, GameID:24, PersonID:14,…},…]
>0: {$id:4, $type:lbD.model.TeamerMVP, lbD.model, GameID:24, PersonID:14,…}
>1: {$id:6, $type:lbD.model.TeamerMVP, lbD.model, GameID:24, PersonID:15,…}
【问题讨论】:
-
显然不知道
Set和TeamerMVP是实体类型。让我们确认是不是这样:在第一个查询的成功回调上放置一个断点。然后在控制台中输入:manager.metadataStore._structuralTypeMap(假设manager是您的 EM)。这将列出客户端上已知的类型。如果您看到Set和TeamerMVP,请告诉我们。如果你这样做......我很惊讶,但我们会知道从哪里开始。如果您不这样做,我怀疑您对服务器上类型的定义存在问题,尤其是您的 EF 映射。当您回答我的问题时,我们会跟进。 -
@Ward 已编辑问题以添加详细信息。谢谢。
-
@Ward 再次编辑以添加更多信息
-
好吧,至少我们知道 Breeze 客户端可以识别类型。您不应该假设
Game.Sets是不可观察的。Object[0]是 KO 可观察数组在控制台中的样子。展开它,您应该会看到该对象具有__ko_proto_函数。但是如果Game.TeamerMVP` 应该返回一个TeamerMVP entity then something IS wrong because that should be afunctiondependentObservable()`。请参阅下一条评论。 -
让我们关注
Game.TeamerMVP。再次断点并告诉我们您在manager.metadataStore.getEntityType('Game').navigationProperties中得到了什么。应该是一个包含 2 个项目的数组,一个描述Game.Sets,一个描述Game.TeamerMVP。我敢打赌你只有一个导航属性……Game.Sets的那个。告诉我们,我们将采取下一步行动。
标签: knockout.js breeze