【问题标题】:EntityManager.createEntity() - Strategies for showing generated ids and default values for user inputEntityManager.createEntity() - 显示生成的 id 和用户输入默认值的策略
【发布时间】:2013-05-31 11:52:00
【问题描述】:

我有 2 个具有 1:M 关系的实体。

Vehicle (Id, RetailPrice, StockOn, VehicleInfoId) and 
VehicleInfo (Id, Year, Make, Model, ICollection<Vehicle>)

这两个 ID 都是用户指定的(字符串),但是因为 Breeze 需要唯一的键(即使是临时的)我必须使用 id = breeze.core.getUuid() 创建实体。 此外,Year 和 RetailPrice 设置为 0(Year 是 int,RetailPrice 是小数)。

一旦我将这些实体绑定到“新车表单”,这些值就会立即显示给用户,而实际上我希望它们为空白...... 处理这个问题的最佳方法是什么? 我的一些想法是:

  1. 添加其他属性(通过初始化程序)并使用这些属性绑定到表单上。然后在保存之前,交换属性。
  2. 在初始化程序(而不是构造函数)中“清除”这些属性......
  3. 是否可以使用自定义 KO 绑定处理程序?

有没有更好的办法?

这是我目前所拥有的(使用 #2,但我不确定这是否正确)

/viewmodels/vehicleadd.js

var vehicle = ko.observable();
var viewModel = {
    title: 'Add New Vehicle',
    vehicle: vehicle,
};
return viewModel;
function activate() {
    vehicle(datacontext.createVehicle());
}

/services/datacontext.js

function init() {
    logger.debug(datacontext, 'Initializing data context...');
    return manager.fetchMetadata()
        .then(model.configureMetadataStore(manager.metadataStore))
        .then(model.applyValidators)
        //.then(loadLookups)
        .fail(initFailed);
}

function createVehicle() {
 var newVehicleInfo = manager.createEntity('VehicleInfo');
 var newVehicle = manager.createEntity('Vehicle');
 newVehicle.vehicleInfo(newVehicleInfo);

 return newVehicle;
}

/services/model.js

function configureMetadataStore(metadataStore) {
    logger.debug(model, 'Configuring metadata store...');
    extendVehicle(metadataStore);
    extendVehicleInfo(metadataStore);
}

function extendVehicle(metadataStore) {
    // --- custom constructor ---
    var vehicleCtor = function () {
        this.id = ko.observable(breeze.core.getUuid()); // must have for Breeze to work...
    };
    // --- initializer ---
    var vehicleInitializer = function (vehicle) {
        // defaults
        vehicle.id(null);                       // user to input
        vehicle.retailPrice(null);              // user to input
        vehicle.stockedOn(moment().format());   // set to current date & time
        // additional, non persisted properties
        vehicle.isBeingEdited = ko.observable(false);
        vehicle.isBeingSaved = ko.observable(vehicle.entityAspect.isBeingSaved);             
    };
    // --- register custom ctor & initializer ---
    metadataStore.registerEntityTypeCtor(EntityNames.Vehicle, vehicleCtor, vehicleInitializer);
}

function extendVehicleInfo(metadataStore) {
    // --- custom constructor ---
    var vehicleInfoCtor = function () {
        this.id = ko.observable(breeze.core.getUuid());
    };
    // --- initializer ---
    var vehicleInfoInitializer = function (vehicleInfo) {
        // defaults
        vehicleInfo.year = ko.observable(moment().format());
        // additional, non persisted properties
        vehicleInfo.isBeingEdited = ko.observable(false);
        vehicleInfo.isBeingSaved = ko.observable(vehicleInfo.entityAspect.isBeingSaved);
        // computed properties
        vehicleInfo.Description = ko.computed(function () {
            return vehicleInfo.year() + ' ' + vehicleInfo.make() + ' ' + vehicleInfo.model();
        });             
    };
    // --- register custom ctor & initializer ---
    metadataStore.registerEntityTypeCtor(EntityNames.VehicleInfo, vehicleInfoCtor, vehicleInfoInitializer);
}

更新 #1

经过一些测试,查询时似乎#2 不起作用。 在(重新)阅读“Extending Entities”文档(查找“实体创建序列”段落)之后,它特别指出在创建实体和查询的两种情况下都会调用初始化函数。因此,在初始化程序中“清除”Ids、RetailPrice 会中断查询和导入......

【问题讨论】:

    标签: knockout.js breeze


    【解决方案1】:

    我会考虑添加在初始化程序中计算的读/写敲除 (KO)。

    当值为 GUID ...或您设计的任何其他唯一临时值时,计算的“读取”端将返回空白。

    “写入”端将 (a) 确认缓存中没有其他实体拥有该键,然后 (b) 用新值覆盖该键。 “读取”端现在将显示该值,因为它不再是“临时”的。

    如果您在任何其他关联中使用这些键,您会受到伤害;您必须手动修复它们......也许在您的 KO 计算写入逻辑中。

    我假设您已经为用户输入的值与其他用户输入的数据库中的另一个键发生冲突的可能性做好了准备。

    我会省去你关于语义键的讲座(如“不要使用它们”);我认为某些遗留数据库会将您置于此位置。

    【讨论】:

    • 谢谢!是的,我别无选择,只能让用户指定密钥(并远程验证以确保其唯一性)。我想在某些情况下这是必须的(想想用户名是 PK 并且他们可以选择它的用户)......这个 KO 计算的“写入”方面已经有点毛茸茸......让我几乎没有想要将实体属性绑定到表单,而不是拥有“以表单为中心”的 KO 可观察对象,然后在保存时创建实体并保存它...属性的重复,但它可能更容易...:(
    • 顺便说一句,对于清除原始属性的默认值(例如整数属性默认为 0)以便显示在表单上的任何建议?
    • 是的,不要觉得你总是必须绑定到一个实体。有时,使用纯“ItemViewModel”来收集用户输入更有意义,然后,只有在它通过验证后,您才创建或更新实体。也许这就是其中一种情况。
    • 我不明白你关于清除默认值的问题
    • 当您创建具有例如不可为空的 int 属性(例如 Year)的实体时,Breeze 将其设置为“0”(与 .NET 中的行为相同)。一旦我将实体属性绑定到表单字段,它就会显示 0,但我希望清除该字段以便用户可以输入它。我再次理解了行为背后的原因,但是由于有很多属性,那么我要么不得不求助于 1)使用读/写逻辑添加 KO 计算,要么 2)具有特定的视图模型并且在用户单击保存之前不创建实体(然后创建实体使用表单视图模型)...任何一种方法都有点 PITA,恕我直言...有其他方法吗?
    猜你喜欢
    • 2014-05-26
    • 2022-07-11
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    相关资源
    最近更新 更多