通过现有的微风创建实体 [英] Breeze create entity from existing one

查看:49
本文介绍了通过现有的微风创建实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经动了好几天了。



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



首先,我创建了此解决方案:

  newCar(datacontext.createCar()); 
newCar()。property1(oldCar()。property1());
newCar()。property2(oldCar()。property2());
...

这很丑,在我证明自己可以做到之后,当然,申请的要求是使所有内容都可复制-我绝不会这样做!某处必须有副本。在挖掘了很多东西之后,甚至试图在微风中改变某些东西,我也无法做以下事情:

  manager .createEntity('Car',oldCar); 

现在,最新的解决方案比第一个更可行,但是仍然需要比我更多的代码

  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);

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



我应该提到Car实体中有一些ICollections,但是这种破解式的解决方案忽略了它们,可以对其进行改进,但是目前我可以解决这个问题自己有一些.forEach循环。

解决方案

我们正在后台进行此类工作。准备就绪时,我们会通知您。没有承诺或时间。



同时,我对此付诸行动。我决定利用Breeze EntityManager.exportEntities 方法这一事实知道如何克隆实体。如果您阅读该方法的微风源代码,就会知道它很棘手。



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

  function cloneItem(item){
//导出无元数据,然后解析导出的字符串。
var export = JSON.parse(manager.exportEntities([item],false));
//从导出
中提取实体var type = item.entityType;
复制副本= export.entityGroupMap [type.name] .entities [0];
//删除entityAspect
删除copy.entityAspect;
//删除键属性
type.keyProperties.forEach(function(p){delete copy [p.name];});

//副本提供create
的初始值return manager.createEntity(type,copy);
}

像您一样,它保留了外键属性,这意味着引用导航属性



像您一样,将不会填充到父实体的值(从缓存中获取值)。



不会填充集合导航属性。这种方法不知道如何克隆孩子。这也不是不言而喻的。



2013年12月15日更新



由于您的要求,我已重新实施具有克隆孩子的能力(集合导航)。我遵循了您建议的语法,因此用法如下:

  cloneItem(something,['collectionProp1','collectionProp2 ']); 

请注意,我再次依靠Breeze出口来完成繁重的工作



警告:此代码非常脆弱,不能在所有型号上通用化

  function cloneItem(item,collectionNames){
var manager = item.entityAspect.entityManager;
//导出不带元数据的文件,然后解析导出的字符串。
var export = JSON.parse(manager.exportEntities([item],false));
//从导出
中提取实体var type = item.entityType;
复制副本= export.entityGroupMap [type.name] .entities [0];
//删除entityAspect(要做的是:从嵌套的复杂类型中删除complexAspect)
delete copy.entityAspect;
//删除键属性(假设键是由商店生成的)
type.keyProperties.forEach(function(p){delete copy [p.name];});

//副本为create
提供初始值。var newItem = manager.createEntity(type,copy);

if(collectionNames&& collectionNames.length){
//仅可以处理带有单个PK值的父对象
var parentKeyValue = newItem.entityAspect.getKey()。值[0];
collectionNames.forEach(copyChildren);
}
返回newItem;

函数copyChildren(navPropName){
//待办事项:添加更多错误处理功能
var navProp = type.getNavigationProperty(navPropName);
如果(navProp.isScalar)返回; //仅复制集合导航。待办事项:应该扔吗?

//此方法仅复制子项(依赖实体),而不复制相关的父项
//子项(依赖项)导航具有相反的FK名称,而不是FK名称
var fk = navProp.invForeignKeyNames [0]; //如果返回(!fk),则只能处理带有单个FK值
的子级;

//微风`getProperty`获取所有模型库的值,例如KO和Angular
var children = item.getProperty(navPropName);
if(children.length === 0)返回;

//复制所有孩子
var childType = navProp.entityType;
children = JSON.parse(manager.exportEntities(children,false));
var个副本= children.entityGroupMap [childType.name] .entities;

copy.forEach(function(c){
delete c.entityAspect;
//删除键属性(假定键是存储生成的)
childType.keyProperties。 forEach(function(p){delete c [p.name];});
//将副本的FK父级设置为新项的PK
c [fk] = parentKeyValue;
//仅创建它们会导致Breeze将它们添加到父
manager.createEntity(childType,c);
});
}


I've been pounding my head for a few days now.

Imagine you have a car sales management application. You sell different models. Your Car model has 50 properties. Just for the example, let's say that you want to sell Bugatti Veyron. Now, you just received 5 of those cars. So, I log in to my application, create first Bugatti Veyron with specific ID. Then I want to add 2nd one, but there is a problem - I would have to write down all of those properties again! I'd like to have a Copy button and I'd just change serial number, breeze would change ID and voila, two cars in there!

For hack sake, at first I created this solution:

newCar(datacontext.createCar());
newCar().property1(oldCar().property1());
newCar().property2(oldCar().property2());
...

it was ugly, and after I proved I can do it, of course, request for application was to make everything copyable - no way I would do that! There must be a copy somewhere. After digging a lot of things, even trying to change some stuff in breeze itself, I couldn't do something like:

manager.createEntity('Car', oldCar);

Now, latest solution is a bit more viable than first one, but still requires more code than I would want and is not as intuitive as it could be:

        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);

Is there any other "cleaner" way of making a new Entity with exactly the same properties, but of course, different id?

I should mention that Car entity has some ICollections in it, but this hack-ish solution ignores them which could be improved, but currently I handle that myself with a few .forEach loops.

解决方案

We're working on such a thing in the back room. We'll let you know when its ready. No promises or timing.

Meanwhile, I took a crack at it. I decided to leverage the fact that the Breeze EntityManager.exportEntities method knows how to clone an entity. If you read the breeze source code for that method, you know it's tricky.

This is what I came up with (as a civilian, not a Breeze developer):

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);
}

Like yours, it preserves the foreign key properties which means that a reference navigation property to a parent entity will have a value drawn from cache if the source had such a value.

Like yours, the collection navigation properties won't be populated. This method doesn't know how to clone the children. Nor is it self-evident that it should. That's extra credit for you.

Update 15 Dec 2013

Because you asked, I've re-implemented with ability to clone children (collection navigations). I've followed the syntax in you suggested so the usage would be:

cloneItem(something, ['collectionProp1', 'collectionProp2']); 

Note that I'm again relying on Breeze export to do the heavy lifting

Warning: this code is extremely fragile and not generalizable to all models

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);
        });
    }

这篇关于通过现有的微风创建实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆