Breeze从现有实体创建实体

Dom*_*tus 4 javascript breeze

我已经好几天了.

想象一下,你有一个汽车销售管理应用程序.你卖不同的型号.您的汽车模型有50个属性.仅举例来说,假设你想卖掉布加迪威龙.现在,你刚收到5辆这样的车.所以,我登录我的应用程序,创建第一个具有特定ID的Bugatti Veyron.然后我想添加第二个,但有一个问题 - 我将不得不再次写下所有这些属性!我想要一个复制按钮,我只是更改序列号,微风会改变ID和瞧,那里有两辆车!

为了黑客的缘故,起初我创建了这个解决方案:

newCar(datacontext.createCar());
newCar().property1(oldCar().property1());
newCar().property2(oldCar().property2());
...
Run Code Online (Sandbox Code Playgroud)

它很难看,经过我的证明我可以做到,当然,请求申请是为了让一切都可以复制 - 我不会这样做!某处必须有副本.在挖掘了很多东西后,甚至试图在微风中改变一些东西,我做不了类似的事情:

manager.createEntity('Car', oldCar);
Run Code Online (Sandbox Code Playgroud)

现在,最新的解决方案比第一个解决方案更可行,但仍然需要比我想要的更多的代码,并且不像它那样直观:

        var newObject = {};
        manager.metadataStore._structuralTypeMap[oldCar.entityType.name].dataProperties.forEach(function (singleProperty) {
                if (!singleProperty.isPartOfKey)
                newObject[singleProperty.name] = oldCar[singleProperty.name];
            });
        var newCar = manager.createEntity('Equipment', newObject);
Run Code Online (Sandbox Code Playgroud)

有没有其他"更清洁"的方法来制作具有完全相同属性的新实体,但当然,不同的ID?

我应该提到Car实体中有一些ICollections,但是这个hack-ish解决方案忽略了可以改进的那些,但是目前我自己处理了一些.forEach循环.

War*_*ard 10

我们正在后面的房间做这样的事情.我们会在准备好的时候通知您.没有承诺或时间.

与此同时,我对它采取了一个裂缝.我决定利用Breeze EntityManager.exportEntities方法知道如何克隆实体这一事实.如果您阅读该方法的breeze源代码,您就会知道它很棘手.

这就是我提出的(作为平民,而不是Breeze开发人员):

function cloneItem(item) {
    // export w/o metadata and then parse the exported string.
    var exported = JSON.parse(manager.exportEntities([item], false));
    // extract the entity from the export
    var type = item.entityType;
    var copy = exported.entityGroupMap[type.name].entities[0];
    // remove the entityAspect
    delete copy.entityAspect; 
    // remove the key properties
    type.keyProperties.forEach(function (p) { delete copy[p.name]; });

    // the "copy" provides the initial values for the create
    return manager.createEntity(type, copy);
}
Run Code Online (Sandbox Code Playgroud)

与您的一样,它保留了外键属性,这意味着如果源具有这样的值,则父实体的引用导航属性将具有从缓存中提取的值.

与您的一样,不会填充集合导航属性.此方法不知道如何克隆子项.它不应该是不言而喻的.这对你来说是额外的功劳.

2013年12月15日更新

因为你问过,我已经重新实现了克隆孩子的能力(收集导航).我已经按照您建议的语法进行操作,因此用法如下:

cloneItem(something, ['collectionProp1', 'collectionProp2']); 
Run Code Online (Sandbox Code Playgroud)

请注意,我再次依靠Breeze导出进行繁重的工作

警告:此代码非常脆弱,并不适用于所有型号

function cloneItem(item, collectionNames) {
    var manager = item.entityAspect.entityManager;
    // export w/o metadata and then parse the exported string.
    var exported = JSON.parse(manager.exportEntities([item], false));
    // extract the entity from the export
    var type = item.entityType;
    var copy = exported.entityGroupMap[type.name].entities[0];
    // remove the entityAspect (todo: remove complexAspect from nested complex types)
    delete copy.entityAspect;
    // remove the key properties (assumes key is store-generated)
    type.keyProperties.forEach(function (p) { delete copy[p.name]; });

    // the "copy" provides the initial values for the create
    var newItem = manager.createEntity(type, copy);

    if (collectionNames && collectionNames.length) {
        // can only handle parent w/ single PK values
        var parentKeyValue = newItem.entityAspect.getKey().values[0];
        collectionNames.forEach(copyChildren);
    }
    return newItem;

    function copyChildren(navPropName) {
        // todo: add much more error handling
        var navProp = type.getNavigationProperty(navPropName);
        if (navProp.isScalar) return; // only copies collection navigations. Todo: should it throw?

        // This method only copies children (dependent entities), not a related parent
        // Child (dependent) navigations have inverse FK names, not FK names
        var fk = navProp.invForeignKeyNames[0]; // can only handle child w/ single FK value
        if (!fk) return; 

        // Breeze `getProperty` gets values for all model libraries, e.g. both KO and Angular
        var children = item.getProperty(navPropName);
        if (children.length === 0) return;

        // Copy all children
        var childType = navProp.entityType;
        children = JSON.parse(manager.exportEntities(children, false));
        var copies = children.entityGroupMap[childType.name].entities;

        copies.forEach(function(c) {
            delete c.entityAspect;
            // remove key properties (assumes keys are store generated)
            childType.keyProperties.forEach(function (p) { delete c[p.name]; }); 
            // set the FK parent of the copy to the new item's PK               
            c[fk] = parentKeyValue;
            // merely creating them will cause Breeze to add them to the parent
            manager.createEntity(childType, c);
        });
    }
Run Code Online (Sandbox Code Playgroud)