I am having trouble with the lazy, eager and explicit loading design patterns common in C# ORM libraries, specifically with derived types that have their own collections.
For example, I want to persist the model below:
public abstract class Offer
{
public int Id { get; set; }
}
public class DiscountOffer : Offer
{
public float Percent { get; set; }
}
public class ColourOffer : Offer
{
public List<string> Colours { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "Unknown";
public IList<Offer> Offers { get; set; } = new List<Offer>();
}
I can easily map and save this to a database using either Entity Framework or NHibernate, the problem comes when I then want to retrieve a full product from the database and send it over the wire using WCF.
If I have the following product:
new Product
{
Name = "Chair",
Offers = new List<Offer>
{
new DiscountOffer { Percent = 0.2f },
new ColourOffer
{
Colours = new List<string>
{
"Red", "Blue", "Green"
}
},
}
};
If the product is lazy loaded then it is encapsulated in a proxy so that it knows when fetch the sub-collections. This presents a problem as the serialization will fail as the type is not as expected.
I found a few answers to this problem:
- Disable lazy loading and eager/explicit load. This works until you meet the the abstract collection. I could find a way to
Include
/Fetch
theColourOffer.Colours
path:
NHibernate:
session.Get<Product>(1).Fetch(p => p.Offers) // If ColourOffer Fetch Colours?
EF:
DbSet<Product> Products { get; set; }
// ...
Products.Include(p => p.Offers) // If ColourOffer Include Colours?
Use DTOs and AutoMapper. I have gathered this is generally a good idea but I run into the same issue of AutoMapper not knowing what to do with the proxy class and so I have to disable lazy loading which takes me back to point 1.
Use a
IDataContractSurrogate
to load the content on serialization. I tried a couple of the implementations floating around on the web but I could not get any to work. I believe this is because the session was being closed by the point of serialization and so the data for the collection could not be fetched.
I now do not know what to do. I just want to load a full product but I cannot find a solution and it is driving me insane.