Исключение OData: не допускается рекурсивный цикл сложных типов.

Выставляю сложный тип через 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.ArgumentException» возникло в System.Web.Http.OData.dll, но не было обработано в пользовательском коде.

Дополнительная информация: Сложный тип «RemoteFile» имеет ссылку на себя через свойство «RelatedFiles». Рекурсивный цикл сложных типов не допускается.

Если есть обработчик этого исключения, программа может быть безопасно продолжена.

Любое предложение приветствуется.


person maomao    schedule 03.02.2014    source источник


Ответы (4)


Похоже, что RemoteFile имеет больше смысла быть типом сущности, а не сложным типом. Типы сущностей могут иметь свойства, указывающие на исходный тип, именно так вы настроили RemoteFile. Ваше определение типа также имеет ключевое свойство, которое используется для типов сущностей, а не для сложных типов. (Подумайте о сложных типах как об удобном способе группировки набора скалярных свойств. Типы сущностей — это первоклассные типы вашей системы, где каждый экземпляр может быть однозначно идентифицирован.)

Итак, вместо этого:

modelBuilder.ComplexType<RemoteFile>();

Попробуй это:

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

Эта строка создаст как тип сущности RemoteFile, так и набор сущностей RemoteFiles. Набор сущностей является контейнером для всех экземпляров типа сущности.

Так почему же рекурсия разрешена для типов сущностей, но не для сложных типов? Когда вы запрашиваете сущность, по умолчанию сервер не будет получать данные ссылочных сущностей. Вы можете явно запрашивать данные объекта, на который указывает ссылка, используя $expand в запросе, но вы не можете расширяться бесконечно. С другой стороны, комплексные значения всегда будут включены, когда вы запросите их родителя. Поэтому, если у вас есть круговое комплексное значение, вы создадите переполнение стека при попытке сериализовать его.

person Jen S    schedule 03.02.2014

Вам случайно не нужно явно игнорировать свойство навигации?

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

Надеюсь, это поможет :)

person Malcolm Swaine    schedule 21.05.2015
comment
Однако это удалит свойство из модели, то есть оно останется только как частные данные. Например, в методе Get это не будет возвращено. - person Diomos; 08.12.2017

У меня такая же проблема. У меня была модель с более чем 100 сущностями, и я попытался добавить только две для тестов.

Решение: ДОБАВЬТЕ ВСЕ ОБЪЕКТЫ в 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). Эти сущности можно использовать только косвенно через отношения открытых сущностей.

person Johan Alzate    schedule 30.01.2015
comment
Это не всегда решает проблему OP, потому что OP явно хочет объявить его как сложный тип, но очень полезный ответ, если ваш тип должен был быть сущностью, а OData обрабатывает его как сложный тип :) - person Chris Schaller; 23.06.2017

Сообщение об ошибке "Сложный тип "RemoteFile" имеет ссылку на себя через свойство "RelatedFiles". Рекурсивный цикл сложных типов не допускается". связано с ограничением библиотеки OData веб-API, в частности внутренней работы класса ODataConventionModelBuilder. Это блокирующая проблема для многих людей, отслеживаемая здесь на GitHub.

person Bruce Johnston    schedule 03.06.2018