如何管理聚合根的新Breeze实体?

时间:2013-05-29 19:54:33

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

我有一个拥有Customer的域模型,而Customer又有1个地址(1:1)和1个或多个Phone numers(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会抱怨(“错误:如果没有先设置其键或将其entityType'AutoGeneratedKeyType'属性设置为'None'以外的其他属性,则无法将对象附加到EntityManager)。但是,如果我生成临时密钥(使用breeze.core.getUuid()或其他东西),那么它会显示在我的Id表单字段中,我真的希望最终用户指定它....我有吗求助于扩展具有额外字段的实体,然后在保存之前进行交换和验证(我根本不喜欢这个想法)?还有更好的方法吗?
  • 为了启用/禁用表单上的按钮,我正在跟踪EntityManager中是否有更改。但每次创建实体时,它都会自动处于“添加”状态,因此hasChanges为true。我想要的是只有当用户编辑表单时才会选择更改(因此会对底层实体进行更改)。解决这个问题的最佳方式是什么?
顺便说一句,我已经看到this recommendation为实体注册自定义构造函数(我已经实现了它但我仍然不清楚如何让用户提供自己的id并仅在用户编辑时将实体标记为已修改...)

2 个答案:

答案 0 :(得分:2)

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

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

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

  3. 如果您使用第二种方法进行答案2,则可以使用ko数据绑定轻松启用和禁用您的按钮。创建实体时,将其值保存到viewmodel(custSource)。然后你可以添加到保存按钮data-bind =" disable:custSource == Customer(),enable:custSource!= Customer()"。 (您可能需要使用语法 - 我尚未对该部分进行测试)

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

    PS。你应该知道我相信Breeze希望Knockout被定义为“ko'”,而Durandal肯定希望它被淘汰出局,所以你可能需要一张地图' ; require.config中的属性

答案 1 :(得分:0)

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

  1. 创建客户实体
  2. 用户修改该实体
  3. 保存更改
  4. 相反,试试这个:

    1. 用户输入客户信息
    2. 创建并保存客户实体
    3. 我意识到这并没有真正回答你的问题,但我发现第二种方法更容易实现。只需让用户输入创建客户所需的所有信息,然后将这些值提供给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 ---