我在OData V4(Asp.net WebApi)上有一个OWIN

一切正常,除了当我尝试查询4级$expand时。

我的查询看起来像:

http://domain/entity1($expand=entity2($expand=entity3($expand=entity4)))

我没有收到任何错误,但是我的回应中没有计划最后的扩展。

更多信息:
  • 我已将MaxExpandDepth设置为10。
  • 我所有的实体都是EntitySets
  • 我正在使用ODataConventionModelBuilder
  • 我打开了一个SQL分析器,可以看到查询(和结果)是正确的。这是执行查询后发生的一些筛选器。
  • 我已经在网上搜索,没有找到合适的内容。
  • 我尝试了不同的4级实体$expands,但它们也无法正常工作。

  • 编辑:

    我已经覆盖了OnActionExecuted:
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);
    
        var objectContent = actionExecutedContext.Response.Content as ObjectContent;
        var val = objectContent.Value;
    
        var t = Type.GetType("System.Web.OData.Query.Expressions.SelectExpandWrapperConverter, System.Web.OData");
        var jc = Activator.CreateInstance(t) as JsonConverter;
        var jss = new JsonSerializerSettings();
        jss.Converters.Add(jc);
    
        var ser = JsonConvert.SerializeObject(val, jss);
     }
    

    序列化的值包含entity4。

    我仍然不知道哪个组件会删除管道中的entity4。

    编辑#2:

    我已经在DefaultODataSerializerProvider和所有其他ODataEdmTypeSerializer's上创建了一个适配器。我看到在此过程中,entity4的$expand存在,并且在该navigationProperty(entity4)上调用ODataResourceSerializer.CreateNavigationLink方法时,该方法将返回null。

    我跳到了源代码中,可以看到SerializerContext.Items的项目中未包含entity4,并且SerializerContext.NavigationSource为null。

    具体来说,我使用的是System.Web.OData, Version=6.1.0.10907

    最佳答案

    好的,所以我注意到问题是由于我的导航属性为EdmUnknownEntitySet类型,并且导航属性查找返回null(源代码带有错误的TODO ..):

    /// <summary>
    /// Finds the entity set that a navigation property targets.
    /// </summary>
    /// <param name="property">The navigation property.</param>
    /// <returns>The entity set that the navigation propertion targets, or null if no such entity set exists.</returns>
    /// TODO: change null logic to using UnknownEntitySet
    public override IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty property)
    {
        return null;
    }
    

    所以我知道我的问题出在EdmUnknownEntitySet上。

    我深入研究了代码,发现需要将ContainedAttribute添加到我的导航属性中。

    由于我的解决方案属于通用存储库,因此已将其添加到“所有启动”导航属性中:
    builder.OnModelCreating = mb => mb.StructuralTypes.SelectMany(s => s.NavigationProperties
                .Where(np => np.Multiplicity == EdmMultiplicity.Many)).Distinct().ForEach(np => np.Contained());
    
    //......
    
    var model = builder.GetEdmModel();
    

    10-06 06:54