Проблема с использованием Include () при сериализации классов POCO Entity Framework 4 с WCF - PullRequest
2 голосов
/ 29 января 2011

У меня есть служба WCF с моделью Entity Framework 4, использующая классы POCO, которые сериализуются и отправляются клиентским приложениям. У меня LazyLoadingEnabled и ProxyCreationEnabled установлены на false, и я использую Linq для Entites, чтобы запросить сущность и вернуть ее через List<> клиенту. Все идет отлично, когда я не использую Include ():

public List<TBLTable1> GetTBLTable1(string pCode)
{
  using (PcFactoryEntities oPcFactoryDB = new PcFactoryEntities())
  {
    oPcFactoryDB.ContextOptions.ProxyCreationEnabled = false;
    oPcFactoryDB.ContextOptions.LazyLoadingEnabled = false;
    var oRS = oPcFactoryDB.TBLTable1
      .Where(c => c.Code == pCode).ToList();
    XmlObjectSerializer serializer = new DataContractSerializer(typeof(TBLTable1));
    serializer.WriteObject(new XmlTextWriter(Console.Out) { Formatting = Formatting.Indented }, oRS[0]);
    return oRS;
  }
}

После запроса Linq я использую сериализатор для имитации процесса сериализации, который происходит, когда класс POCO отправляется клиенту, и я прекрасно работаю. Однако, когда я добавляю Include () для загрузки одного из списка навигации для класса, он начинает сериализацию всего списка навигации Table2, как если бы для LazyLoadingEnabled было задано значение true, и он продолжает сериализацию, вероятно, всей базы данных !

public List<TBLTable1> GetTBLTable1(string pCode)
{
  using (PcFactoryEntities oPcFactoryDB = new PcFactoryEntities())
  {
    oPcFactoryDB.ContextOptions.ProxyCreationEnabled = false;
    oPcFactoryDB.ContextOptions.LazyLoadingEnabled = false;
    var oRS = oPcFactoryDB.TBLTable1
      .Include("TBLTable2")
      .Where(c => c.Code == pCode).ToList();
    XmlObjectSerializer serializer = new DataContractSerializer(typeof(TBLTable1));
    serializer.WriteObject(new XmlTextWriter(Console.Out) { Formatting = Formatting.Indented }, oRS[0]);
    return oRS;
  }
}

Почему это происходит? Разве LazyLoadingEnabled со значением false не должен применяться к классу, включенному вручную, и возвращать все его списки навигации в null, как это происходит со всеми другими списками навигации для Table1? Есть ли способ исправить это, чтобы я мог вернуться с Таблицей 1 к некоторым спискам навигации, заполненным с их списками навигации, установленными на null?
Tks

Ответы [ 2 ]

2 голосов
/ 29 января 2011

Вместо того, чтобы пытаться напрямую сериализовать объект, попробуйте проецировать его на DTO и сериализовать его.Я согласен с тем, что вы видите странным поведением - но может случиться так, что внутренний граф EF вступает во владение, когда вы сериализуете сущности, но если вы сериализуете DTO, EF не должен вмешиваться.

Например:

var dto = oPcFactoryDB.TBLTable1
                      .Where(x => x.Code == pCode)
                      .Select(x => new SpecialisedDTO
                      {
                         PropertyOne = x,
                         PropertyTwo = x.TBLTable2
                      }).ToList();

И затем сериализовать это.

После того, как вы спроецировали, вам не нужно загружать нагрузку - EF получит то, что нужно, на основе вашего запроса.

В ситуациях N-уровня обычно рекомендуется передавать DTO по проводам, а не чистым объектам POCO.

0 голосов
/ 30 января 2011

Есть ли у вас свойство навигации от TBLtable1 до TBLtable2? .Include () используется для включения сущностей, которые связаны с отношениями FK, а .Include () передается Имя свойства навигации.

Таким образом, если у вас есть объект Person с NavigationProperty к объекту адресов с именем PersonAddresses, вы должны выполнить следующее, чтобы получить Person и его адреса.

var p = dbContext.Person
         .Where(x => x.Id == id)
         .Include("PersonAddresses")
         .SelectFirstOrDefault;
...