在使用WCF序列化Entity Framework 4 POCO类时使用Include()时出现问题

时间:2011-01-29 01:01:10

标签: entity-framework serialization entity-framework-4 linq-to-entities poco

我有一个带有Entity Framework 4模型的WCF服务,使用序列化并发送到客户端应用程序的POCO类。我将LazyLoadingEnabledProxyCreationEnabled设置为false,我正在使用Linq来实现查询实体,并通过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的所有其他导航列表一样?有没有办法解决这个问题所以我可以使用Table1返回一些导航列表,其导航列表设置为null
TKS

2 个答案:

答案 0 :(得分:2)

尝试投影到DTO并对其进行序列化,而不是尝试直接序列化实体。我同意你看到的是奇怪的行为 - 但是当你序列化实体时,EF内部图可能会接管,但是如果你序列化DTO,EF就不应该介入。

E.g:

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

然后序列化。

自投射以来,您不需要急切加载 - EF会根据您提供的查询获取所需内容。

在N-Tier情况下,通过线路传输DTO通常是很好的做法,而不是纯粹的POCO实体。

答案 1 :(得分:0)

您是否在TBLtable1到TBLtable2上有导航属性? .Include()用于包含与FK关系链接的实体,并且.Include()传递导航属性的名称。

因此,如果您有一个具有NavigationProperty的Person Entity到名为PersonAddresses的地址实体,那么您将执行以下操作以获取Person及其地址。

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