WebApi с EF Code First генерирует ошибку при наличии родительских и дочерних отношений - PullRequest
11 голосов
/ 18 ноября 2011

Я ломаю голову над этой проблемой.Я нашел что-то в Интернете об этом, но не четкий ответ.Моя проблема:

У меня есть классы в разделе Model веб-приложения MVC3: ParentClass и ChildClass В ParentClass есть свойство Children типа List

Я использовал EF Code First, который аккуратно генерируетродительская таблица и дочерняя таблица для меня в базе данных.

Теперь мне нужна служба REST, которая возвращает список или один ParentClass.

Когда я удаляю свойство Children из ParentClassнет проблем.Но с propoerty Дети там я получаю сообщение об ошибке.

Ошибка: "The type System.Data.Entity.DynamicProxies.ParentClass_A0EBE0D1022D01EB84B81873D49DEECC60879FC4152BB115215C3EC16FB8003A was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}

Какой-то код:

Классы:

     public class ParentClass
{
    public int ID { get; set; }
    public string Name {get;set;}
    public virtual List<ChildrenClass> Children { get; set; }

}

public class ChildrenClass
{
    public int ID { get; set; }
    public string MyProperty { get; set; }
}

Служба:

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
public class MyService
{

    static MyContext db;
    public MyService() { db = new MyContext(); }


    [WebGet(UriTemplate = "")]
    public List<ParentClass> GetParents()
    {
        var result = db.Parents.ToList();
        return result;

    }

Я не получу результат при вызове этой службы.Что я делаю не так?

Ответы [ 3 ]

12 голосов
/ 18 ноября 2011

Мне пришлось отключить ProxyCreation в конфигурации контекста:

[OperationContract] 
[WebGet(UriTemplate = "")] 
public List<ParentClass> GetParents() 
{ 
     using (DBContext context = new DBContext()) 
     {
         context.Configuration.ProxyCreationEnabled = false; 
         List<ParentClass> parents = context.Parents
             .Include("Children") 
             .ToList();
         return parents; 
      }
}

Это сработало для меня нормально.

0 голосов
/ 11 мая 2012

В некоторых ситуациях простое решение состоит в том, чтобы использовать класс-оболочку, чтобы все представленные свойства были известными типами.

Обычно вы не будете использовать ObjectContext или DbContext в ваших классах контроллеров в любом случае, поэтому вна более раннем уровне (бизнес-уровне или уровне службы) вы можете выполнить быстрый перевод объектов, поступающих из БД, в объекты стиля ViewModel, аналогично тому, что вы делали бы в приложении MVC, но вместо передачи их в возвращаемое представлениеих звонящему.

Может быть, вы не можете использовать его во всех случаях, но часто это выполнимый компромисс.

0 голосов
/ 18 ноября 2011

Похоже, что сериализуются прокси-классы для ваших POCO, моя первая рекомендация будет использовать proxydatacontractresolver: http://msdn.microsoft.com/en-us/library/system.data.objects.proxydatacontractresolver.aspx.

Также я бы поработал над тем, чтобы все было явно прописано при загрузке данных для отправки черезвеб-служба ... т.е.

Изменить родительский класс на

public class ParentClass
{
    public int ID { get; set; }
    public string Name {get;set;}
    public List<ChildrenClass> Children { get; set; }

}

Измените содержимое, чтобы отключить отложенную загрузку: Отключите отложенную загрузку по умолчанию в Entity Framework 4

И явно укажите, что вы хотите загрузить при возврате данных, передаваемых по сети.

[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
    var result = db.Parents.Include("Children").ToList();
    return result;

}

Посмотрите на следующий ответ: Entity Framework Code First - Eager Загрузка неработать как положено? для более продвинутых Включите звонки.

Также совет из опыта, я бы не стал возвращать ваши классы данных по проводам, поскольку они формируют контракт для потребителя вашего веб-сервиса,Лучше всего иметь другой набор классов, в который сопоставляются значения данных.

Таким образом, если ваши классы данных изменяются, вам не нужно менять клиента веб-службы, если это явно не требуется.

А использование подкачки важно, если вы ожидаете 1000 строк в классах Parent или Child, в противном случае вы выбираете N + 1 select, см .: Что такое SELECT N + 1? .

...