2

我正在尝试让 BreezeJS 库与 SAP OData 服务一起使用。这适用于读取实体,但我无法解析链接的对象。

我的 EntityType 是一个 OrgObject。

<EntityType Name="OrgObject" sap:content-version="1">
  <!-- ... -->
  <NavigationProperty Name="Children" Relationship="ZGW_ORGSTRUCTURE.OrgObject_To_Children" FromRole="FromRole_OrgObject_To_Children" ToRole="ToRole_OrgObject_To_Children"/>
</EntityType>

我有一个链接来解决所有链接的 OrgObjects(链接名为 Children)。

<Association Name="OrgObject_To_Children" sap:content-version="1">
  <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="1" Role="FromRole_OrgObject_To_Children"/>
  <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="*" Role="ToRole_OrgObject_To_Children"/>
</Association>

所以,这个微风查询正在工作:

var query = new breeze.EntityQuery().from("OrgObjects");
manager.executeQuery(query).then(function(data) {
  data.results.forEach(function(item) {
    console.log(item);
  });
}).fail(/*...*/);

我如何从这个对象中调用“孩子”?

尝试1:

var query = new breeze.EntityQuery().from("OrgObjects");
manager.executeQuery(query).then(function(data) {
  data.results.forEach(function(item) {
    console.log(item);
    // ...
    var Children = item.Children();
    // ...
  });
}).fail(/*...*/);

这会导致错误:

message: "Object [object Object] has no method 'children'"

尝试2:

var query = new breeze.EntityQuery().from("OrgObjects");
manager.executeQuery(query).then(function(data) {
  data.results.forEach(function(item) {
    console.log(item);
    // ...
    item.entityAspect.loadNavigationProperty("Children").then(function(data) {
      console.log(data.results);
      data.results.forEach(function(item) {
        console.log(item);
      });
    }).fail(function(e) {
      console.log(e);
    });
    // ...
  });
}).fail(/*...*/);

这会导致错误:

“propertyOrExpr”参数必须是“字符串”

尝试 3:

var query = new breeze.EntityQuery().from("OrgObjects").expand("Children");
manager.executeQuery(query).then(function(data) {
  data.results.forEach(function(item) {
    console.log(item);
    // ...
    console.log(item.Children);
    console.log( item.Children.length );
    // ...
  });
}).fail(/*...*/);

结果: item.Children是一个对象。但是item.Children.length = 0item.Children当我检查 http 响应时,子项是从服务器获取的,但在对象中不可用。

控制台输出:

Finance Department
[parentEntity: Object, navigationProperty: ctor, arrayChanged: ctor, _addsInProcess: Array[0], push: function…]
    _addsInProcess: Array[0]
    _getEventParent: function () {
    _getPendingPubs: function () {
    arrayChanged: ctor
    length: 0
    load: function (callback, errorCallback) {
    navigationProperty: ctor
    parentEntity: Object
    pop: function () {
    push: function () {
    shift: function () {
    splice: function () {
    unshift: function () {
    __proto__: Array[0]
0

谁能帮帮我?我的 OData 服务中是否缺少某些内容?

4

3 回答 3

1

问题被“解决”了。

1->n 关系只能在定义了逆属性 (n->1) 的情况下使用。据我所知,在 SAP Gateway 中无法定义反向关系。为了测试它,我创建了 2 个关系:

<Association Name="OrgObject_To_Children" sap:content-version="1">
    <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="1" Role="FromRole_OrgObject_To_Children"/>
    <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="*" Role="ToRole_OrgObject_To_Children"/>
</Association>
<Association Name="OrgObject_To_Children_inverse" sap:content-version="1">
    <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="*" Role="FromRole_OrgObject_To_Children_inverse"/>
    <End Type="ZGW_ORGSTRUCTURE.OrgObject" Multiplicity="1" Role="ToRole_OrgObject_To_Children_inverse"/>
</Association>

然后我在微风中改变了这个

function updateCrossEntityRelationship(np) {
    var metadataStore = np.parentType.metadataStore;
    var incompleteTypeMap = metadataStore._incompleteTypeMap;

    // ok to not find it yet
    var targetEntityType = metadataStore._getEntityType(np.entityTypeName, true);
    if (targetEntityType) {
        np.entityType = targetEntityType;
    }

    var assocMap = incompleteTypeMap[np.entityTypeName];
    if (!assocMap) {
        addToIncompleteMap(incompleteTypeMap, np);
    } else {
        var inverse = assocMap[np.associationName];

        /* enable inverse relationship for SAP GATEWAY */
        // search for inverse links
        if( !inverse ){
            var associationName = "";
            if(np.associationName.indexOf("_inverse") > 0){
                associationName = np.associationName.replace("_inverse", "");
            }else{
                 associationName = np.associationName + "_inverse";
            }
            inverse = assocMap[associationName];
        }
        /* end enable inverse relationship for SAP GATEWAY */

        if (inverse) {
            removeFromIncompleteMap(incompleteTypeMap, np, inverse);
        } else {
            addToIncompleteMap(incompleteTypeMap, np);
        }
    }
};

但这并没有解决所有问题,我必须更改另一件事才能使其正常工作。不知道这是bug还是与SAP Gateway有关。

function mergeRelatedEntitiesCore(rawEntity, navigationProperty, parseContext) {
    var relatedRawEntities = rawEntity[navigationProperty.nameOnServer];
    if (!relatedRawEntities) return null;

    // needed if what is returned is not an array and we expect one - this happens with __deferred in OData.
    /* original code 
    if (!Array.isArray(relatedRawEntities)) return null;

    var relatedEntities = relatedRawEntities.map(function(relatedRawEntity) {
        return visitAndMerge(relatedRawEntity, parseContext, { nodeType: "navPropItem", navigationProperty: navigationProperty });
    });

    return relatedEntities;
    end original code */

    if (!Array.isArray(relatedRawEntities.results)) 
        return null;

    relatedRawEntities.results = relatedRawEntities.results.map(function(relatedRawEntity) {
        return visitAndMerge(relatedRawEntity, parseContext, { nodeType: "navPropItem", navigationProperty: navigationProperty });
    });

    return relatedRawEntities.results;

}

我只测试了这个用于读取操作。稍后我将检查更新操作。

kr,约阿希姆

于 2013-04-22T07:53:32.537 回答
0

@Jowa - 感谢您为将 SAP 和 BreezeJS 结合在一起所做的努力。

您发现expand这是急切加载 parent 的孩子的方式OrgObject

当导航属性正常工作时,您可以通过...按需加载它们loadNavigationProperty...尽管对每个查询结果逐一执行会非常低效。这种情况要求expand

显然,Breeze 正在努力处理您的导航属性,因为它无法识别支持该关系的子实体中的外键。

您不必为 1..m 关系的双方定义导航属性。最常被忽略的一侧是 1->N 侧(父->子)属性。例如,我们大多数人会省略Gender.Person,因为我们不想要 collection male.Persons

在您的情况下,如果我理解正确,您认为定义了 1->N ( OrgObject.Children) 而不是 N->1 导航 ( Child.OrgObject)。那么这也应该工作!

但无论如何,要使导航属性在任一方向上工作,元数据都必须识别子实体类型中的外键 (FK) 属性。

出于某种原因,Breeze 似乎没有得到这些信息。

破解 BreezeJS 本身......虽然很聪明......不应该是必要的。

我们愿意提供帮助。我们需要以下信息:

  • Child服务器上的类定义...突出显示其OrgObjectFK 属性
  • 对象中的OrgObject- 和 -Child相关元数据metadataStore
  • 来自元数据文件的OrgObject- 和 -相关 JSONChild
于 2013-05-31T20:09:13.910 回答
0

免责声明:我对 Breeze 不是很熟悉,但我猜测可能会发生什么。

从 Breeze关于导航属性的文档中,它说它不会延迟加载导航属性。因此,如果item.Children()数据在本地尚未完全可用,它就不会出去获取数据。您需要明确请求将子数据与有效负载的其余部分一起检索,以便在本地获取此信息。通常在 OData 中,这是通过$expand请求 URL 中的查询参数完成的。在 Breeze 中(根据我链接到的那个文档),它是通过如下.expand()方法完成的:

var query = new breeze.EntityQuery()
              .from("OrgObjects")
              .expand("Children");
于 2013-04-18T17:50:25.210 回答