Javascript Breeze-惰性负载复杂类型

Javascript Breeze-惰性负载复杂类型,javascript,breeze,Javascript,Breeze,我试图在breeze中延迟加载一个复杂类型,但无法找到一种实现方法 我之所以想使用复杂类型而不是导航方式,是因为我必须使用的服务没有像breeze那样使用CRUD。我必须将一个对象及其所有子对象(标量和非标量)发送到负责存储数据的单个服务方法(插入/更新/删除) 我尝试使用导航属性来实现这一点,但这意味着我必须创建一个实体数组来发送到API控制器,然后在那里重新创建整个对象。这将是困难的,但更困难的是,因为子对象中没有外键(这是我到目前为止看到的所有示例中的情况),这使得再次映射它们非常困难 对

我试图在breeze中延迟加载一个复杂类型,但无法找到一种实现方法

我之所以想使用复杂类型而不是导航方式,是因为我必须使用的服务没有像breeze那样使用CRUD。我必须将一个对象及其所有子对象(标量和非标量)发送到负责存储数据的单个服务方法(插入/更新/删除)

我尝试使用导航属性来实现这一点,但这意味着我必须创建一个实体数组来发送到API控制器,然后在那里重新创建整个对象。这将是困难的,但更困难的是,因为子对象中没有外键(这是我到目前为止看到的所有示例中的情况),这使得再次映射它们非常困难

对于复杂类型,我没有这个问题(或者我没有意识到)

我必须使用这样的对象结构:

1.家长:产品(类别)

1.1儿童:软件包(阵列)

1.2儿童:分裂级别(阵列)

1.2.1Grandchild:权限(数组)

1.2.1.1品牌:药店(阵列)

1.2.2Grandchild:splitLevel(类)

软件包与产品一起加载,这很好。 但是,此数据契约中不包括拆分级别(因为它需要太多数据,并且不会经常被查询)。请求此数据时,会向产品中添加一个布尔值,以指示已加载这些数据,从那时起,还需要将这些数据发送到服务器

加载产品时,会导致以下问题: 对象不支持属性或方法“getProperty”

这是由breeze中的_initializeInstance方法引起的:

if (initFn) {
    if (typeof initFn === "string") {
        initFn = instance[initFn];
    }
    initFn(instance);
}
this.complexProperties && this.complexProperties.forEach(function (cp) {
    var ctInstance = instance.getProperty(cp.name);
    cp.dataType._initializeInstance(ctInstance);
});
实例为空,无法从中获取任何属性

有办法解决这个问题吗? 是否有一种方法可以在不获取多个实体的情况下使用导航属性;因此,我可以发送单个对象,而无需使用此选项:

if (product.entityAspect.entityState.isUnchanged()) {
    product.entityAspect.setModified();
}

// Packages
var entitiesToSave = product.packages().slice();// copy

// Split Levels
if (product.storeSplitLevels) {
    product.splitLevelsLoaded(true);
    // TODO: Add split levels to entities to save
}

// Product Details
entitiesToSave.push(product);

没有更多的信息,我不完全清楚您在问什么,但我们计划在EntityManager的Breeze API中添加一个函数,允许您使用任意数据结构调用任意端点,并通过JsonResultsAdapter将调用结果(如果有)合并回EntityManager

在此之前,您可以通过绕过EntityManager.saveChanges,直接使用Breeze ajax适配器调用端点来完成其中的一部分。差不多

var ajaxImpl = breeze.config.getAdapterInstance("ajax");
ajaxImpl.ajax({
        type: "POST",
        url: url,
        dataType: 'json',
        contentType: "application/json",
        data: bundle,   // arbitrary data to server.
        success: function (httpResponse) {
            // perform custom client side code 
        },
        error: function (httpResponse) {

        }
    });

我按照你的建议创建了一个定制包

对于其他有相同问题的开发人员,我做了以下工作:

  • 创建一个自定义展开函数,该函数提供与breeze中的展开函数相同的功能,但将其扩展以包含导航属性

  • 添加用于从实体创建保存捆绑包的方法

  • 代码:


    很抱歉,我的问题是:1。是否可以延迟加载嵌套的复杂类型;包含复杂类型的数组,该数组包含其他复杂类型。我无法让它工作(来自breeze的代码块)。2.如果没有,是否有一种方法可以使用导航属性,而不必让所有实体处于同一级别,但定义它们的方式与传入datacontract相同。但你实际上用你的评论回答了这个问题。
    function createEntitySaveBundle(entity) {
        var rawEntity = unwrapInstance(entity);
        var entities = [];
        rawEntity.entityAspect = {
            entityTypeName: entity.entityType.name,
            defaultResourceName: entity.entityType.defaultResourceName,
            entityState: entity.entityAspect.entityState.name,
            autoGeneratedKey: {
                propertyName: entity.entityType.keyProperties[0].nameOnServer,
                autoGeneratedKeyType: entity.entityType.autoGeneratedKeyType.name
            }
        };
        entities.push(rawEntity);
    
        return { entities: entities, saveOptions: {} };
    }
    
    function unwrapInstance(entity) {
        var rawObject = {};
        var stype = entity.entityType || entity.complexType;
        var val;
        var entities;
    
        stype.dataProperties.forEach(function (dp) {
            if (dp.isUnmapped) {
                val = entity.getProperty(dp.name);
                val = transformValue(val, dp, false);
                if (val !== undefined) {
                    rawObject.__unmapped = rawObject.__unmapped || {};
                    // no name on server for unmapped props
                    rawObject.__unmapped[dp.name] = val;
                }
            } else if (dp.isComplexProperty) {
                if (dp.isScalar) {
                    rawObject[dp.nameOnServer] = unwrapInstance(entity.getProperty(dp.name));
                } else {
                    entities = entity.getProperty(dp.name);
                    rawObject[dp.nameOnServer] = entities.map(function (co) { return unwrapInstance(co); });
                }
            } else if (dp.isDataProperty) {
                val = entity.getProperty(dp.name);
                val = transformValue(val, dp);
                if (val !== undefined) {
                    rawObject[dp.nameOnServer] = val;
                }
            }
        });
    
        stype.navigationProperties.forEach(function (np) {
            if (np.isScalar) {
                // Doesn't occur with products, enabling this results in an endless loop without checking if the navigation property already exists in the rawObject (recursive..)
                // rawObject[np.nameOnServer] = unwrapInstance(entity.getProperty(np.name));
            } else {
                entities = entity.getProperty(np.name);
                rawObject[np.nameOnServer] = entities.map(function (eo) { return unwrapInstance(eo); });
            }
        });
    
        return rawObject;
    }
    function transformValue(val, prop) {
        if (prop.isUnmapped) return;
        if (prop.dataType === breeze.DataType.DateTimeOffset) {
            // The datajs lib tries to treat client dateTimes that are defined as DateTimeOffset on the server differently
            // from other dateTimes. This fix compensates before the save.
            val = val && new Date(val.getTime() - (val.getTimezoneOffset() * 60000));
        } else if (prop.dataType.quoteJsonOData) {
            val = val != null ? val.toString() : val;
        }
        return val;
    }