0

I'm trying to lazy load a complex type in breeze but cannot figure out a way to accomplish this.

The reason I would like to use a complex type and not the navigation way, is the service I have to consume is not doing CRUD the same way as breeze. I have to send one single object with all its subobjects (both scalar and non scalar) to a single service method responsible for storing data (insert/update/delete).

I tried to do this with navigation properties but this means I have to create an array of entities to send to an API controller, and there recreate the entire object. This would be difficult, but even more so because there are no foreign keys in the child objects (which is the case in all samples I've seen until now) making it a pain to map them again.

With complex types, I don't have this issue (or not that I'm aware of).

I have to consume an object structure like this:

1.Parent: product (class)

1.1Child: packages (array)

1.2Child: splitLevels (array)

1.2.1Grandchild: permissions (array)

1.2.1.1Grandgrandchild: pharmacies (array)

1.2.2Grandchild: splitLevel (class)

Packages are loaded together with the product, this works just fine. Howevers, splitLevels are not included in this datacontract (since it requires too much data and will not be consulted that often). When requesting this data, a boolean is added to the product to indicate they have been loaded, from then on it is required to send them to the server as well.

When loading product, this results in an issue: Object doesn't support property or method 'getProperty'

This is caused by the _initializeInstance method in breeze:

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

The instance is empty, no properties can be fetched from it.

Is there any way to work around this? Is there a way to use navigation properties without getting multiple entities; so I can send a single object without using this:

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

2 回答 2

1

我按照您的建议创建了一个自定义捆绑包。

对于其他有同样问题的开发人员,我做了以下事情:

  1. 创建一个自定义 unwrap 函数,它提供与微风中的 unwrap 函数相同的功能,但也将其扩展为包含导航属性。

  2. 添加从实体创建保存包的方法。

代码:

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;
}
于 2013-10-22T09:35:16.547 回答
0

如果没有更多信息,我并不完全清楚您要问什么,但我们计划为 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) {

        }
    });
于 2013-10-09T17:20:43.233 回答