为什么我的 Breeze.js 实体没有创建 ko.observables?

2023-12-13

我使用的 Breeze.js 没有服务器端组件,并使用以下代码在客户端创建实体。根据沃德的要求,我简化了一切,并添加了更多信息。我的 MetaDataStore 配置功能-

function configureMetadataStore(metadataStore) {
        metadataStore.addEntityType({
            shortName: 'Manufacturer',
            namespace: 'StackAndReach',
            autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity,
            dataProperties: {
                id: { dataType: DT.Int64, isPartOfKey: true },
                name: { dataType: DT.String },
                website: { dataType: DT.String},
                approved: {dataType: DT.boolean},
                user_id: { dataType: DT.Int64 }
            }
        });
    }

来自我的服务器的 JSON 响应

{"id":"141","name":"Trek","website":"http:\/\/www.trekbikes.com\/","approved":"1","user_id":"3"}

我的数据上下文中的配置代码(整个设置减去缺少服务器元数据是在约翰·帕帕的课程之后设置的)

var entityQuery = breeze.EntityQuery,
        manager = configureBreezeManager();
function configureBreezeManager() {
        breeze.NamingConvention.camelCase.setAsDefault();
        var ds = new breeze.DataService({
            serviceName: config.remoteServiceName,
            hasServerMetadata: false
        });

        var mgr = new breeze.EntityManager({dataService : ds});
        model.configureMetadataStore(mgr.metadataStore);
        return mgr;
    }

当模型被拉下来时,数据就在那里,但是数据没有包装在 ko.observables 中,并且 init 函数中的 ko.observables/ko.compulated 也不在从查询中传递出来的模型中。如何确保模型的数据包装在 ko.observables 中并添加 ko.compulateds?


这个答案既是对问题的回答,也是分析问题的教程。

第 1 步 - 简化和隔离

让我们从根本上简化,直到找到缺失的步骤。让我们从您拥有的最简单的实体类型开始……最多具有 2 到 5 个属性的实体类型。没有吗?补一张吧减少Manufacturer只是“id”和“name”。我们首先要尝试把机制搞清楚。

您没有在服务器上使用任何微风组件。美好的。选择提供该测试实体数据的服务器端点。让该端点仅通过一个实例传递一个 JSON 数组。向我们展示到达客户端的 JSON...整个 JSON 有效负载,与到达网络时完全相同。内容应该简短;如果不是,那么你的简化还不够。

然后我们可以弄清楚您是否需要 JsonResultsAdapter 以及如果需要的话它应该是什么样子。

向我们展示您填充的确切顺序metadataStore带有 EntityType、ctor 和初始值设定项。坦率地说,在第一个工作之前,我宁愿没有构造函数或初始化程序。

您如何确保EntityManager您创建的是使用该商店吗?我们需要查看您的配置代码以及您如何更新EntityManager并用它来查询端点。

如果您遵循我的建议,就不会有太多代码。也许有二十行。 JSON feed 应约为 10 行。如果您达不到这些数字,则说明您的简化程度还不够。

第 2 步 - 查看更简单的示例

现在您已经重新编写了该示例,我更好地了解了该去哪里查找。

有两件事突然出现在我眼前:

  1. 来自服务器的 JSON 结果
  2. The camelCase命名约定

来自服务器的 JSON

让我们漂亮地打印您提供的 JSON 结果并讨论它们:



{
  "id": "141",
  "name": "Trek",
  "website": "http:\/\/www.trekbikes.com\/",
  "approved": "1",
  "user_id": "3"
}
  

Breeze 不知道如何处理该 JSON 对象,因为它缺少类型信息。对于微风来说,它只是一个任意的物体,也许是投影的结果。

将其与访问 DocCode Web API 的查询的 JSON 结果进行比较。这是为查询生成的 URL:



>http://localhost:47595/breeze/northwind/Suppliers/?$top=1
  

这是(缩写的)JSON 结果



[
   {
      "$id":"1",
      "$type":"Northwind.Models.Supplier, DocCode.Models",
      "SupplierID":1,
      "CompanyName":"Exotic Liquids"
   }
]
  

默认情况下Breeze 客户端需要已序列化的数据JSON.NET,ASP.NET 中的默认序列化程序。

JSON.NET 有效负载是一个节点或节点数组。 JSON.NET 添加了自己的$id and $type每个节点的属性。

我想把你的注意力集中在$type您可能会将其识别为 .NET 类型的全名(带有命名空间的类、程序集名称)。

你可以逃脱没有$id财产。

$id 是一个自动递增的序列化键。通常,同一个对象会在有效负载中出现多次。 JSON.NET 没有重复内容,而是用一个简单的节点代替,例如{$ref: #} where #指的是$id较早的节点。这种方法既减少了有效负载大小,又打破了循环引用。

不过Breeze真的很期待$type财产。这就是它将 JSON 对象/节点连接到元数据中的类型的方式。如果您的制造商示例节点有一个,它可能如下所示:



"$type": "StackAndReach.Manufacturer, MyModel"
  

我不知道你如何在服务器上序列化数据。您似乎正在使用 JSON.NET 以外的其他东西。

太棒了。我只是告诉你 Breeze 默认情况下是如何工作的;它对.NET 非常友好。但 Breeze 不需要 .NET。它是一个纯 JavaScript 库。你只需要告诉它你想要什么。

Use 输入(...)

你能做的最简单的事情就是add toType您的查询.



var query = breeze.EntityQuery.from('Manufacturers')
                  .where( ... )
                  .toType( 'Manufacturer' );
  

通过这种方式,您可以明确声明“制造商”端点返回的顶级节点包含Manufacturer您在元数据中描述的类型。

我敢打赌这会立即对你有用(一旦你修复命名约定问题如下面所描述的)。

这是一种有效的方法,但它有几个缺点。我提两点:

  1. 您必须记住将其添加到每个查询中。

  2. 它只适用于顶级实体; if 不适用于嵌套实体,例如应用时返回的.expand() clause.

我更喜欢教 Breeze 客户端如何自行解释 JSON 结果......使用自定义JsonResultsAdapter.

自定义 JsonResultsAdapter

查看微风埃德蒙兹样本其中 Breeze 客户端使用来自 Edmunds 车辆信息服务的数据。

Edmunds 服务器发送完全不同类型的 JSON 有效负载来响应查询。这是一个片段:



{
   "makeHolder":[
      {
         "id":200347864,
         "models":[
            {
               "link":"/api/vehicle/am-general/hummer",
               "id":"AM_General_Hummer",
               "name":"Hummer"
            }
         ],
         "name":"AM General",
         "niceName":"amgeneral",
         "manufacturer":null,
         "attributeGroups":{

         }
      },
      ... more ...
   ]
}
  

No $type那里也有。 Breeze 开发者做了什么?他写了一个自定义 Breeze JsonResultsAdapter它在文件中应用程序/jsonResultsAdapter.js.

尽管只有 40 行,但我不打算在这里重现该文件。我想让你读一下jsonResultsAdapter文档,拉下 Edmunds 示例,然后自己阅读。

我将总结它的作用以及它是如何工作的。微风呼唤你的jsonResultsAdapter首先是当它收到 JSON 有效负载时,然后是当它处理该有效负载中的每个节点时。您的工作是告诉 Breeze 如何处理该节点,您可以通过调整节点本身并返回描述该节点的元对象来完成。

这是一个片段:



>if (node.id && node.models) {
    // move 'node.models' links so 'models' can be empty array
    node.modelLinks = node.models;
    node.models = [];
    return { entityType: "Make"  }
}
  

此代码片段中有三个活动:

  1. 识别节点的内容(if ...)
  2. 调整节点值(出于任何对您有意义的原因)
  3. 组合并返回“元”对象结果。

专注于#3。这就是开发人员告诉 Breeze“将这个节点变成一个Make entity.

结构型式匹配

你可能会说,“嘿沃德,Manufacturer实体类型与 JSON 对象结构完全匹配。微风应该将其识别为Manufacturer."

Breeze 不会通过匹配类型结构来预测实体类型。我也不认为它应该......因为不同类型通常共享相同的结构。例如:我有一个StatusCode and ProductCode两者都是实体类型{ id: int, name: string}。我们还有很多其他增强功能需要改进;处理类型歧义并不是我们的首要任务。

命名约定

最后,让我们回到我看到的另一个问题。

Your configureBreezeManager方法开始:


breeze.NamingConvention.camelCase.setAsDefault();  

您已将默认命名约定从“same-on-client-and-server”更改为“pascalCase-on-client/CamelCase-on-server”。

通过切换到camelCase惯例,你告诉 Breeze 客户端属性foo应发送到服务器Foo.

这是正确的做法吗?如果您的服务器需要 CamelCase 属性名称,那就是这样。但是,根据 JSON 负载中的属性名称,服务器也需要使用 CamelCase。客户端和服务器上的属性名称相同。如果微风向制造商发送了带有Name属性值而不是name适当的价值。

保留微风默认值,“不执行任何操作”约定。不要覆盖它。从您的文件中删除 pascalCase 约定行configureBreezeManager.

保存更改

我们一直在讨论查询结果。我们根本没有讨论如何将更改保存回服务器。

我确信您有自己的协议(类似 ReST 的东西?)和序列化格式。这是一个完全不同的讨论。我们不要在这个 Stack Overflow 问题中讨论这个问题。我只是提醒您,您可能很快就会为这个问题摸不着头脑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的 Breeze.js 实体没有创建 ko.observables? 的相关文章

  • 使用 knockout.js 防止双击按钮

    禁用按钮以便 Knockout js 不会发生双击的最佳方法是什么 我有一些用户快速点击导致多个 ajax 请求 我认为 knockout js 可以通过多种方式处理这个问题 并希望看到一些替代方案 使用信号量 旋转锁 基本上 您计算一个元
  • 在 KnockoutJS 中更改模型数据时,Javascript 内存泄漏

    我们正在构建一个相当大的单页应用程序 使用 KnockoutJS 作为 数据处理程序 问题是 当更改模型数据时 垃圾收集器不会处理旧模型 看起来如此 该应用程序有大约 12 个不同的模型 其中包含计算的可观察量 您可以使用它们检索关系 在
  • Typescript 中此子范围的问题

    This is ALMOST和其他人一样this到目前为止 我已经读过范围界定问题 除了一个细微的差别之外 这使得提出这个问题变得有意义 imo 现在最初我的问题是范围this使用 Knockout 和 Typescript 因此给出以下内
  • 如何在服务器中处理用于发布目的的日期

    我从 ASP NET MVC 获得了这个值 Date 1446393600000 它在 SQL 数据库中的值是 2015 11 02 这是一个date 仅限日期 并将其作为 javascript 对象进行操作 我使用moment js ht
  • 强制使用原生 Knockout 模板

    我有一个需要 jQuery tmpl 的页面 但我想使用本机淘汰模板 data bind foreach Comments 属性 因为我已经包含了 jQuery tmpl 所以淘汰赛的本机模板被禁用 有没有办法可以强制使用本机功能 Than
  • 如何将 HTML 表格导出到 Chrome 和 IE 支持的 Excel?

    在我的 MVC 项目中 我有一个与 Knockout 绑定的 HTML 表 我正在尝试将表格导出到 Excel 我在客户端尝试使用 JavaScript self exportToExcel function javascript wind
  • 不支持使用微风在同一查询中执行选择和扩展

    我使用 Durandal breeze 开发了一个 asp net 解决方案 这是我获取所有托运人的代码 var query EntityQuery from Shippers select id name street city retu
  • Knockout.js 安全绑定

    我想使用带有淘汰赛的安全绑定 为此我使用敲除安全绑定 js https github com brianmhunt knockout secure binding 谁能解释一下为什么下面的代码不起作用 它会抛出一个错误 未捕获 淘汰 安全
  • 如何使breezejs所需的验证器允许空字符串

    在breezejs中允许所需属性中存在空字符串的首选方式是什么 I found 这个答案 https stackoverflow com questions 19658297 how does breeze saves empty stri
  • MVVM 在 ASP.NET MVC 4 Web 应用程序中扮演什么角色?

    当我正在阅读 ASP NET MVC 4 这本书时 我对 MVVM 感到好奇 我开始谷歌搜索 找不到任何关于使用 MVVM 开发 Web 应用程序的书籍 所以我一定在这里遗漏了一些信息 据我了解 MVVM是通过knockout js和其他框
  • 淘汰赛应用程序的性能调整 - 改进响应时间的指南

    我有一个大型 复杂的页面 严重依赖于 Knockout js 性能开始成为一个问题 但检查调用堆栈并试图找到瓶颈是一个真正的挑战 我在另一个问题中注意到 Knockout js 理解 foreach 和 with https stackov
  • 用于创建类似于 StackOverflow 的分页 UI/链接的淘汰赛模板

    我有一个用于某些分页 UI 的功能 Knockout 模板 可与基于 Knockout 的共享数据网格配合使用 该模板为网格中的每个数据 页面 呈现一个 HREF 该模板可以工作 但它很笨重 因为如果我获取大量数据 那么我最终会在网格下方出
  • 如何使用离线存储和 Knockout.js 实现 MVVM?

    我可以使用 Knockout js 实现 Mvvm 但我想将它与跨浏览器 FF 和 Chrome 支持的 Html 5 离线存储一起使用 我想将 html 对象绑定到离线存储 我没试过 但是有一个knockout localStorage
  • 淘汰赛,内容可编辑(和降价)

    使用由 markdown 字符串支持的 Knockout 绑定处理程序并进行渲染 使用 markdown js 和内置的 html 绑定处理程序 工作正常 但尝试添加内容可编辑行为 并且在可观察值未在模糊时更新或仅使用删除了所有降价格式的文
  • Knockout.js ViewModel 更改回调?

    我正在尝试在 Knockout js 应用程序中实现自动保存功能 有没有办法在 ViewModel 发生变化时分配回调 看看 Ryan Niemeyer 的聪明但肮脏的旗帜 http www knockmeout net 2011 05 c
  • 首选的客户端路由解决方案? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 从外部文件加载淘汰赛模板,无需复杂的引擎?

    我找到了加载外部模板的引擎 插件和函数 但我想知道是否有更简单的方法来做到这一点 像这样的东西吗 模板 html 索引 html div div 这行得通吗 有什么 陷阱 吗 这是我用来加载包含模板集合的模板文件的方法 var loadTe
  • Onclick使用knockout js绑定图像

    我想显示来自 allDoorColorStandard 的图像 HTML 单击 颜色数据 div 我想更新图像 在警报中 我正在获取图像 URL 现在需要绑定到图像标签中 div img class mappimg width 45 hei
  • 单击输入[复选框]的标签将触发父级单击事件两次(淘汰)

    考虑这把小提琴 http jsfiddle net 9rkrahm6 我有一个
  • 使用 Newtonsoft.Json 反序列化 DbGeometry

    我正在使用 Angular Breeze 和 Web API 2 构建 SPA 遵循 John Papa 在他最新的 PluralSight 课程中概述的方法 一切运行良好 我可以将信息拉取 更新 插入 删除回服务器 但是 我正在使用空间类

随机推荐