Принудительная загрузка всех связанных сущностей внутри сущности без знания типов классов сущностей - PullRequest
0 голосов
/ 23 июня 2010

Я пытаюсь сериализовать сущность и все связанные с ней сущности для хранения в виде XML перед физическим удалением сущности (оставляя контрольный журнал).

Я использую DataContractSerializer, который, кажется,обойти мелкую сериализацию, выполняемую при использовании XmlSerializer.

Единственная проблема заключается в том, что только связанные сущности, которые были загружены, сериализуются.

Я пытался создать вспомогательную функцию, котораявозьмет любую сущность и выполнит итерацию, хотя ее свойства ищут связанные сущности для загрузки, однако она не работает на EntityCollection свойствах, потому что я не могу привести их к EntityCollection<EntityObject>.Я пытался использовать EntityObject, так как полагал, что полиморфизм придет мне на помощь, но свойство не будет разыгрывать жалобы, что это другой тип.

Есть идеи?

/// <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.EntityKey);

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

1 Ответ

0 голосов
/ 24 июня 2010

Я нашел решение, которое сделало то, что я хочу:

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

Мне также нужно было изменить параметр processed на ref, чтобы он работал как требуется:

LoadAllRelatedEntities(EntityObject entity, ref List<EntityKey> processed)

В моем случае мне также пришлось добавить некоторую фильтрацию к тем объектам, которые я бы загружал, так как в моем случае многие из них сами ссылались где-то вниз по цепочке и вызывали бесконечные циклы.

...