OData异常:不允许复杂类型的递归循环

问题描述 投票:5回答:4

我通过OData公开了一个复杂的类型。这个班是这样的:

public class RemoteFile 
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string Resource { get; set; }

    public virtual ICollection<RemoteFile> RelatedFiles { get; set; }
}

我通过OData公开它:

    var modelBuilder = new ODataConventionModelBuilder();
    modelBuilder.ComplexType<RemoteFile>();

这是我开始项目时得到的:

System.Web.Http.OData.dll中出现“System.ArgumentException”类型的异常,但未在用户代码中处理

附加信息:复杂类型“RemoteFile”通过属性“RelatedFiles”引用自身。不允许复杂类型的递归循环。

如果存在此异常的处理程序,则可以安全地继续该程序。

任何建议都受到欢迎。

c# recursion odata complextype
4个回答
3
投票

听起来RemoteFile成为实体类型更有意义,而不是复杂类型。实体类型可以具有指向原始类型的属性,这就是您设置RemoteFile的方式。您对类型的定义也有一个键属性,用于实体类型,而不是复杂类型。 (将复杂类型视为对一组标量属性进行分组的便捷方式。实体类型是系统的第一类类型,其中每个实例都可以唯一标识。)

所以不是这样的:

modelBuilder.ComplexType<RemoteFile>();

试试这个:

modelBuilder.EntitySet<RemoteFile>(“RemoteFiles”);

该行将创建实体类型RemoteFile和实体集RemoteFiles。实体集是实体类型的所有实例的容器。

那么为什么递归允许实体类型而不是复杂类型呢?当您要求实体时,默认情况下,服务器不会获取引用实体的数据。您可以在查询中使用$expand明确询问引用实体的数据,但不能无限扩展。另一方面,当您要求父母时,将始终包含复杂值。因此,如果您有一个循环复杂值,则在尝试序列化时会创建堆栈溢出。


2
投票

你是否需要明确地忽略导航属性?

modelBuilder.ComplexType<RemoteFile>().Ignore(x => x.RemoteFile);

希望有帮助:)


2
投票

我有同样的问题。我有一个超过100个实体的模型,我试图只添加两个,用于make测试。

解决方案:向ODataConventionModelBuilder添加所有实体,如下所示:

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Entity1>("Entity1");
builder.EntitySet<Entity2>("Entity2");
builder.EntitySet<Entity3>("Entity3"); 

//... and thus for ALL YOUR ENTITIES.

// If you don't want to expose any entity like EntitySet, simply add to builder like EntityType:
builder.EntityType<Entity4>("Entity4");

即使您不添加实体,构建器也会扫描所有类型(如复杂类型),并且关系会失败。因此,有必要指定所有扫描类型都是实体。

如果您不希望公开所有类似EntitySet,则可以添加到EntityType等构建器,并且您的客户端引用将使用此类,但不会授予您访问EntitySet(CRUD操作)的权限。该实体仅可以通过暴露实体的关系间接使用。


0
投票

错误消息“复杂类型'RemoteFile'通过属性'RelatedFiles'引用自身。不允许复杂类型的递归循环。”是由于Web API OData库的限制,特别是ODataConventionModelBuilder类的内部工作原理。对于许多人来说,这是一个阻塞问题,在GitHub上跟踪here

© www.soinside.com 2019 - 2024. All rights reserved.