Pascal
Pascal

Reputation: 2984

Problem using Include() when serializing Entity Framework 4 POCO classes with WCF

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

Upvotes: 2

Views: 2311

Answers (2)

Shayne Boyer
Shayne Boyer

Reputation: 410

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;

Upvotes: 0

RPM1984
RPM1984

Reputation: 73113

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.

Upvotes: 2

Related Questions