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

发布于 2024-10-14 17:51:14 字数 1824 浏览 2 评论 0原文

我有一个带有 Entity Framework 4 模型的 WCF 服务,使用 POCO 类进行序列化并发送到客户端应用程序。我将 LazyLoadingEnabledProxyCreationEnabled 设置为 false,并且我使用 Linq to Entites 查询实体,并通过 返回它向客户端列出<>。当我不使用 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
塔克斯

I have a WCF service with an Entity Framework 4 model, using POCO classes that are serialized and sent over to client applications. I have LazyLoadingEnabled and ProxyCreationEnabled set to false, and I'm using Linq to Entites to query an Entity, and return it via List<> to the client. Everything goes perfect when I don't use 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;
  }
}

After the Linq query, I use the serializer to simulate the serialization process that happens when the POCO class is sent to the client, and I works great. However, when I add an Include() to load one of the navigation list for the class, it starts serializing all of Table2's navigation's list as if LazyLoadingEnabled was set to true, and it goes on forever serializing probably the whole database!

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;
  }
}

Why is this happening? Shouldn't the LazyLoadingEnabled set to false apply to the class included manually and return all of it's navigation lists to null as it happens with all of the other navigation lists for Table1? Is there a way to fix this so I can return with Table1 some navigations lists filled in with their navigation lists set to null?
Tks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

短暂陪伴 2024-10-21 17:51:14

不要尝试直接序列化实体,而是尝试投影到 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 实体,通常是一种很好的做法。

Instead of trying to directly serialize the entity, try projecting to a DTO and serializing that. I agree what your seeing is bizarre behaviour - but it could be that the EF internal graph is taking over when your serializing the entities, but if you serialize a DTO, EF should not intervene.

E.g:

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

And then serialize that.

Since your projecting, you don't need to eager load - EF will grab what it needs to based on the query you have provided.

It's usually good practice in N-Tier situations to transmit DTO's over the wire, rather than the pure POCO entities.

何必那么矫情 2024-10-21 17:51:14

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

因此,如果您有一个 Person 实体,该实体具有指向名为 PersonAddresses 的地址实体的 NavigationProperty,那么您将执行以下命令以获取该 Person 及其地址。

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

Do you have a Navigation Property on TBLtable1 to TBLtable2? The .Include() is used to include entities that are linked va FK relationships and the .Include() is passed the Name of the Navigation Property.

So if you have a Person Entity with a NavigationProperty to an Addresses Entity called PersonAddresses you would then execute the following in order to get the Person and their addresses.

var p = dbContext.Person
         .Where(x => x.Id == id)
         .Include("PersonAddresses")
         .SelectFirstOrDefault;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文