This project has moved. For the latest updates, please go here.
1
Vote

DbMapping can get child classes in the wrong order

description

Let's say we have classes A and C, which both inherit from class B. The DbMapping constructor will look at them in alphabetical order. It sees that A has an unmapped parent and adds it to nextLevel for later processing. It then maps class B, which succeeds because it has no unmapped parent. It then maps class C. C's parent, B, is now mapped, so it proceeds. Then it processes nextLevel, which includes mapping class A.

So the classes get mapped in order B, C, A. This is a problem because the mapping logic assumes that A will be mapped before C, so it swaps some of the properties between them, and the mappings are incorrect.

I fixed this by first running through the whole list to determine which classes belong in nextLevel, then doing the actual mapping for everything else. In the DbMapping constructor, replace the foreach loop with this:
// If A and C both inherit from B, then we want to add A and C to nextLevel, then map B.
var typeMappingsWithoutUnmappedParents = new Dictionary<string, EntityType>();

foreach (var kvp in typeMappings)
{
    if (mapper.HasUnmappedParent(kvp.Key, kvp.Value))
    {
        nextLevel.Add(kvp.Key, kvp.Value);
    }
    else
    {
        typeMappingsWithoutUnmappedParents.Add(kvp.Key, kvp.Value);
    }
}

foreach (var kvp in typeMappingsWithoutUnmappedParents)
{
    var entityMap = mapper.MapEntity(kvp.Key, kvp.Value);

    if (entityMap == null)
    {
        continue;
    }

    //tableMapping.DbMapping = this;
    _tableMappings.Add(kvp.Key, entityMap);
}
This requires a new function in MapperBase:
public bool HasUnmappedParent(string typeFullName, EdmType edmItem)
{
    try
    {
        PrepareMapping(typeFullName, edmItem);
    }
    catch(ParentNotMappedYetException)
    {
        return true;
    }

    return false;
}
This may be the same as some of the other issues, but I wasn't sure, so I created a new one. Is this project still alive? I'd love to see this fixed in the NuGet package!

comments