2014-02-03 4 views
3

Я выставляю сложный тип через 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» имеет ссылку на себя через свойство «RelatedFil» эс. Рекурсивная петля сложных типов не допускается.

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

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

ответ

3

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

Таким образом, вместо этого:

modelBuilder.ComplexType<RemoteFile>(); 

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

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

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

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

1

У меня была та же проблема. У меня была модель с более чем 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>("Entity3"); 

Даже если вы не добавлять объекты, строитель сканирует все типы, такие как сложные типы, и отношения терпят неудачу. Поэтому необходимо указать, что все отсканированные типы являются объектами.

Если вы не хотите раскрывать все подобные EntitySet, вы можете добавить к строителю, как EntityType, и ссылка на ваш клиент будет использовать этот класс, но не даст вам доступ к EntitySet (операции CRUD). Эти сущности могут использоваться косвенно только через отношения открытых объектов.

+0

Это не всегда исправляет проблему OPS, поскольку OP явно хочет объявить его как сложный тип, но очень полезный ответ, если ваш тип должен был быть entity и OData обрабатывает его как сложный тип :) –

2

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

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

Надежда, что помогает :)

+0

Это, однако, будет отключать свойство от модели, а это означает, что он останется только как личные данные. Например, в методе Get этот метод не будет возвращен. – Diomos

Смежные вопросы