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

时间:2014-02-03 18:41:37

标签: c# recursion odata complextype

我通过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”引用自身。不允许复杂类型的递归循环。

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

欢迎任何建议。

4 个答案:

答案 0 :(得分:3)

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

所以不要这样:

modelBuilder.ComplexType<RemoteFile>();

试试这个:

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

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

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

答案 1 :(得分: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操作)的权限。此实体只能通过暴露实体的关系间接使用。

答案 2 :(得分:2)

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

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

希望有所帮助:)

答案 3 :(得分:0)

错误消息&#34;复杂类型&#39; RemoteFile&#39;通过财产“相关文件”来引用自己。不允许复杂类型的递归循环。&#34;是由于Web API OData库的限制,特别是ODataConventionModelBuilder类的内部工作原理。对于许多人来说,这是一个阻塞问题,在GitHub上跟踪here