【问题标题】:How to manage new Breeze entities which are aggregate roots?如何管理作为聚合根的新 Breeze 实体?
【发布时间】:2014-11-26 01:54:37
【问题描述】:

我有一个域模型,它有一个客户,它又具有 1 个地址 (1:1) 和 1 个或多个电话号码 (1:M)。 客户有用户提供的 PK(字符串),而地址和电话使用身份列(服务器生成)。

我正在努力了解如何为“添加新客户”屏幕管理 Breeze 实体创建。 屏幕上的表单允许用户输入客户、地址和电话数据。

我正在使用 Durandal 和 Knockout,所以我的“customeradd.js”视图模型看起来像这样:

// -- snip ---
    var customer = ko.observable(),
        hasChanges = ko.computed(function () {
            return datacontext.hasChanges();
        });

    var vm = {
        hasChanges: hasChanges,
        customer: customer,
        activate: activate
    };

    return vm;

    function activate() {
        customer(datacontext.createCustomer());
    }
// -- snip ---

还有我的“/services/datacontext.js”:

// -- snip ---
    breeze.NamingConvention.camelCase.setAsDefault();

    var manager = new breeze.EntityManager(config.remoteServiceName);
    var hasChanges = ko.observable(false);

    manager.hasChangesChanged.subscribe(function (eventArgs) {
        hasChanges(eventArgs.hasChanges);
    });

    function createVehicle() {
        return manager.createEntity("Customer");
    }
// -- snip ---

我的问题如下:

  • 创建客户后,是否需要创建地址和电话列表并将它们添加到客户实体,然后才能使其成为可观察的 KO?还是通过 createEntity() 方法自动完成?
  • 如何创建客户但无需指定 ID?如果我将键设置为 null 或 '',Breeze 会抱怨(“错误:无法将对象附加到 EntityManager 而不先设置其键或将其 entityType 'AutoGeneratedKeyType' 属性设置为 'None' 以外的值”)。但是,如果我生成临时密钥(使用轻风.core.getUuid() 或其他),那么它会显示在我的 Id 表单字段中,我真的希望最终用户指定它....我有吗诉诸使用额外字段扩展实体,然后在保存之前进行交换和验证(我根本不喜欢这个想法)?有没有更好的方法?
  • 为了启用/禁用表单上的按钮,我正在跟踪 EntityManager 中是否有更改。但是每次创建实体时,它都会自动处于“添加”状态,因此 hasChanges 为真。我想要的是仅在用户编辑表单时才进行更改(因此对底层实体进行更改)。解决此问题的最佳方法是什么?

顺便说一句,我已经看到this recommendation 为实体注册自定义构造函数(我已经实现了它,但我仍然不清楚如何让用户提供他们自己的 id 并仅在用户编辑实体时将其标记为已修改.. .)

【问题讨论】:

    标签: asp.net-web-api breeze single-page-application durandal


    【解决方案1】:

    我意识到这已经有一段时间了,但这是我的想法(以防有人来看)。

    1. 如果您使用 entityManager 创建客户,并且在元数据中正确指定了所有内容,您只需创建客户并根据需要添加电话号码/地址。 Breeze 会自动使实体的属性可观察(如果指定正确并且当 Breeze 知道正在使用 KO)

    2. 如果你只能按照你说的方式去做,那么你就会陷入困境。理想情况下,您将有一个用户输入的 ID,它不是密钥(尽管您仍然可以强制它是唯一的)和一个数据库生成的密钥,Breeze 将在幕后管理(分配一个否定密钥,直到它被保存到数据存储,然后在没有您输入的情况下更新密钥和所有相关密钥)。

    3. 如果您对答案 2 使用第二种方法,则可以使用 ko 数据绑定轻松启用和禁用您的按钮。创建实体时,将其值保存到视图模型 (custSource)。然后您可以将 data-bind="disable: custSource == Customer(), enable: custSource != Customer()" 添加到保存按钮。 (你可能需要尝试一下语法——我还没有测试过那部分)

    我认为你不需要自定义构造函数,除非你做的事情与我理解的不同。

    PS。您应该知道,我相信 Breeze 希望将 Knockout 定义为 'ko',而 Durandal 肯定希望它是 'knockout',因此您可能需要在 require.config 中添加一个 'map' 属性

    【讨论】:

      【解决方案2】:

      我认为您可以通过对实体创建采取稍微不同的方法来解决您的一些问题。这是您当前的方法:

      1. 创建客户实体
      2. 用户修改该实体
      3. 保存更改

      试试这个:

      1. 用户输入客户信息
      2. 创建并保存客户实体

      我意识到这并不能真正回答您的问题,但我发现第二种方法更容易实施。只需让用户输入创建客户所需的所有信息,然后将这些值提供给createEntity

      customeradd.js

      // -- snip ---
          var vm = {
              customerId: ko.observable(),
              address: ko.observable(""),
              phoneNumbers: ko.observableArray([]),
      
              submit: submit
          };
      
          return vm;
      
          function submit() {
              datacontext.createCustomer(
                  vm.customerId(), 
                  vm.address(),
                  vm.phoneNumbers());
          }
      // -- snip ---
      

      /services/datacontext.js

      // -- snip ---
          /**
           * Creates a new customer.
           * @param {int} id - The customer's id number.
           * @param {string} address - The customer's address.
           * @param {string[]} phoneNumbers - An array of the customer's phone numbers.
           */
          function createCustomer(id, address, phoneNumbers) {
              return manager.createEntity("Customer",
              {
                  id: id,
                  address: address,
                  phoneNumber: phoneNumbers
              });
          }
      // -- snip ---
      

      【讨论】:

      • 您的建议肯定会让它更易于管理,但这也意味着对于每个表单,我都会有一个几乎 1:1 的 viemodel 字段与实体属性...想象一下具有 20- 的客户实体30 个属性,然后必须有一个具有这么多 ko 可观察对象的视图模型...现在将其与域模型中的 40-50 个实体相乘...这是很多重复,你不觉得吗?
      • 是的,这将是一大堆重复,而且绝对会很糟糕......我会看看我是否能想出一些更好的东西。
      • 查看这个 q 以及 (stackoverflow.com/q/16928767/481904),它有一些由 @Ward(微风“家伙”之一)的 cmets :) - 我的目标是避免重复绑定表单 Breeze 实体同时拥有有意义的用户体验(请参阅我关于 Breeze 实体默认值的评论)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      相关资源
      最近更新 更多