2

我有一个域模型,它有一个客户,它又具有 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 为真。我想要的是仅在用户编辑表单时才进行更改(因此对底层实体进行更改)。解决这个问题的最佳方法是什么?

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

4

2 回答 2

2

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

  1. 如果您使用 entityManager 创建您的客户,并且元数据中的所有内容都正确指定,您只需创建客户并根据需要添加电话号码/地址。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”属性

于 2014-11-25T17:54:37.780 回答
0

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

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

相反,试试这个:

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

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

客户添加.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 ---
于 2013-06-05T11:46:30.723 回答