I'm trying to serialize an entity and all its related entities for storing as xml before physically deleting the entity (leaving an audit trail).
I'm using a DataContractSerializer
which seems to be getting around the shallow serialization performed when using an XmlSerializer
.
The only trouble is that only related entities that have been loaded get serialized.
I've tried to create a helper function that will take any entity and iterate though its properties looking for related entities to load, however its failing on EntityCollection
properties because I can't cast them to EntityCollection<EntityObject>
. I was trying to use EntityObject
as I figured polymorphism would come to my aid, but the property won't cast complaining it's a different type.
Any ideas?
/// <summary>
/// Forces loading of all related entities.
/// </summary>
/// <param name="processed">Processed entities, used to prevent infinite looping.</param>
private static void LoadAllRelatedEntities(EntityObject entity, List<EntityKey> processed)
{
// Check we haven't already processed this entity
foreach (EntityKey key in processed)
{
if (entity.EntityKey == key)
return; // Exit without doing anything more with this entity
}
processed.Add(entity.En开发者_如何学JAVAtityKey);
// Pull in all child entities
foreach (PropertyInfo p in entity.GetType().GetProperties())
{
if (p.PropertyType == typeof(EntityReference) || p.PropertyType.BaseType == typeof(EntityReference))
{
if (p.GetValue(entity, null) != null)
{
EntityReference e = (EntityReference)p.GetValue(entity, null);
if (!e.IsLoaded)
e.Load();
// Load child entities
IEnumerator eEnum = e.GetEnumerator();
while (eEnum.MoveNext())
{
LoadAllRelatedEntities((EntityObject)eEnum.Current, processed);
}
}
}
else if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>))
{
EntityCollection<EntityObject> e = (EntityCollection<EntityObject>)p.GetValue(entity, null);
if (!e.IsLoaded)
e.Load();
// Load child entities
IEnumerator eEnum = e.GetEnumerator();
while (eEnum.MoveNext())
{
LoadAllRelatedEntities((EntityObject)eEnum.Current, processed);
}
}
}
}
I found a solution that did what I want:
else if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>))
{
IEnumerable pEnum = (IEnumerable)p.GetValue(entity, null);
IRelatedEnd pEnd = (IRelatedEnd)p.GetValue(entity, null);
pEnd.Load();
// Load child entities
IEnumerator eEnum = pEnum.GetEnumerator();
while (eEnum.MoveNext())
{
LoadAllRelatedEntities((EntityObject)eEnum.Current, ref processed);
}
}
I also needed to change the processed
param to a ref so it worked as required:
LoadAllRelatedEntities(EntityObject entity, ref List<EntityKey> processed)
In my case I also had to add some filtering to which entities I would load as in my case a lot were self-referencing somewhere down the chain and so caused endless looping.
精彩评论