我们可以在 olingo odata 中创建最多 3 个段的导航属性吗

Can we create navigation properties upto 3 segments in olingo odata

我有一个要求,我们需要在 URI 中发送 3 个实体集

例如,{serviceRoot}/Entity1('ID')/Entity2('ID')/Entity3

我已经浏览了 olingo git 存储库,但只能找到 2 个片段(对于 3 个片段 Not Implemented Exception 被抛出。

我想了解 URL({serviceRoot}/Entity1('ID')/Entity2('ID')/Entity3) 是否有效?

Olingo 使用的版本是 4.5

从 OData Sepcifiion 的角度来看,拥有 3 级甚至 n 级都很好 'navigation properties',URL 的第一段是实体或实体集,然后您将必须创建导航属性,这些属性绑定到(读取return)和实体集或实体。

你得到 Not Implemented Exception 异常的原因是,如果你通读 readEntityCollection 的代码,你会发现下面的片段

if (segmentCount == 2){ //navigation: e.g. DemoService.svc/Categories(3)/Products

此处检查该段是否为第 3 部分并将其视为导航 属性 但如果您更深入,它只是有一个 else 条件,它会抛出异常。

为了实现您的目的,您必须在代码中实现此逻辑才能更深入一个(或更多)级别

下面是完整代码供参考

public void readEntityCollection(ODataRequest 请求,ODataResponse 响应,UriInfo uriInfo,ContentType responseFormat) 抛出 ODataApplicationException,SerializerException {

EdmEntitySet responseEdmEntitySet = null; // for building ContextURL
EntityCollection responseEntityCollection = null; // for the response body

// 1st retrieve the requested EntitySet from the uriInfo
List<UriResource> resourceParts = uriInfo.getUriResourceParts();
int segmentCount = resourceParts.size();

UriResource uriResource = resourceParts.get(0); // the first segment is the EntitySet
if (! (uriResource instanceof UriResourceEntitySet)) {
    throw new ODataApplicationException("Only EntitySet is supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(),Locale.ROOT);
}

UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) uriResource;
EdmEntitySet startEdmEntitySet = uriResourceEntitySet.getEntitySet();

if(segmentCount == 1){ // this is the case for: DemoService/DemoService.svc/Categories
    responseEdmEntitySet = startEdmEntitySet; // first (and only) entitySet

    // 2nd: fetch the data from backend for this requested EntitySetName
    responseEntityCollection = storage.readEntitySetData(startEdmEntitySet);
}else if (segmentCount == 2){ //navigation: e.g. DemoService.svc/Categories(3)/Products
    UriResource lastSegment = resourceParts.get(1); // don't support more complex URIs
    if(lastSegment instanceof UriResourceNavigation){
        UriResourceNavigation uriResourceNavigation = (UriResourceNavigation)lastSegment;
        EdmNavigationProperty edmNavigationProperty = uriResourceNavigation.getProperty();
        EdmEntityType targetEntityType = edmNavigationProperty.getType();
        responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty);

        // 2nd: fetch the data from backend
        // first fetch the entity where the first segment of the URI points to
        // e.g. Categories(3)/Products first find the single entity: Category(3)
        List<UriParameter> keyPredicates = uriResourceEntitySet.getKeyPredicates();
        Entity sourceEntity = storage.readEntityData(startEdmEntitySet, keyPredicates);
        // error handling for e.g.  DemoService.svc/Categories(99)/Products
        if(sourceEntity == null) {
            throw new ODataApplicationException("Entity not found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
        }
        // then fetch the entity collection where the entity navigates to
        responseEntityCollection = storage.getRelatedEntityCollection(sourceEntity, targetEntityType);
    }
}else{ // this would be the case for e.g. Products(1)/Category/Products
    throw new ODataApplicationException("Not supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(),Locale.ROOT);
}
    // 3rd: create and configure a serializer
    ContextURL contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).build();
    final String id = request.getRawBaseUri() + "/" + responseEdmEntitySet.getName();
    EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().contextURL(contextUrl).id(id).build();
    EdmEntityType edmEntityType = responseEdmEntitySet.getEntityType();

    ODataSerializer serializer = odata.createSerializer(responseFormat);
    SerializerResult serializerResult = serializer.entityCollection(this.srvMetadata, edmEntityType, responseEntityCollection, opts);

    // 4th: configure the response object: set the body, headers and status code
    response.setContent(serializerResult.getContent());
    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
    response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());   
}

给出答案,总之没有段数限制, {service Root}/Entity 1.12=])/Entity 2('ID')/Entity3) 是有效的,Shiva

很好地解释了其余部分