Skip to content

Commit

Permalink
Fix of Mapping provider to allow use of inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
PospisilBohumir committed May 7, 2015
1 parent 9780621 commit 75989b9
Showing 1 changed file with 92 additions and 34 deletions.
126 changes: 92 additions & 34 deletions Source/EntityFramework.Extended/Mapping/MetadataMappingProvider.cs
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
Expand All @@ -10,17 +11,17 @@
namespace EntityFramework.Mapping
{
/// <summary>
/// Use <see cref="MetadataWorkspace"/> to resolve mapping information.
/// Use <see cref="MetadataWorkspace" /> to resolve mapping information.
/// </summary>
public class MetadataMappingProvider : IMappingProvider
{
/// <summary>
/// Gets the <see cref="EntityMap" /> for the specified <typeparamref name="TEntity" />.
/// Gets the <see cref="EntityMap" /> for the specified <typeparamref name="TEntity" />.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="query">The query to use to help load the mapping data.</param>
/// <returns>
/// An <see cref="EntityMap" /> with the mapping data.
/// An <see cref="EntityMap" /> with the mapping data.
/// </returns>
public EntityMap GetEntityMap<TEntity>(ObjectQuery query)
{
Expand All @@ -31,12 +32,12 @@ public EntityMap GetEntityMap<TEntity>(ObjectQuery query)
}

/// <summary>
/// Gets the <see cref="EntityMap" /> for the specified <paramref name="type" />.
/// Gets the <see cref="EntityMap" /> for the specified <paramref name="type" />.
/// </summary>
/// <param name="type">The type of the entity.</param>
/// <param name="dbContext">The database context to load metadata from.</param>
/// <returns>
/// An <see cref="EntityMap" /> with the mapping data.
/// An <see cref="EntityMap" /> with the mapping data.
/// </returns>
public EntityMap GetEntityMap(Type type, DbContext dbContext)
{
Expand All @@ -46,40 +47,34 @@ public EntityMap GetEntityMap(Type type, DbContext dbContext)
}

/// <summary>
/// Gets the <see cref="EntityMap" /> for the specified <paramref name="type" />.
/// Gets the <see cref="EntityMap" /> for the specified <paramref name="type" />.
/// </summary>
/// <param name="type">The type of the entity.</param>
/// <param name="objectContext">The object context to load metadata from.</param>
/// <returns>
/// An <see cref="EntityMap" /> with the mapping data.
/// An <see cref="EntityMap" /> with the mapping data.
/// </returns>
public EntityMap GetEntityMap(Type type, ObjectContext objectContext)
{
var entityMap = new EntityMap(type);
var metadata = objectContext.MetadataWorkspace;

// Get the part of the model that contains info about the actual CLR types
var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));

// Get the entity type from the model that maps to the CLR type
var entityType = metadata
.GetItems<EntityType>(DataSpace.OSpace)
.First(e => objectItemCollection.GetClrType(e) == type);
var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
var entityType = metadata.GetItems<EntityType>(DataSpace.OSpace).Single(e => objectItemCollection.GetClrType(e) == type);

// Get the entity set that uses this entity type
var entitySet = metadata.GetItems<EntityContainer>(DataSpace.CSpace)
.SelectMany(a => a.EntitySets)
.Where(s => s.ElementType.Name == entityType.Name)
.FirstOrDefault();

.SelectMany(a => a.EntitySets).FirstOrDefault(s => s.ElementType.Name == entityType.Name);

// Find the mapping between conceptual and storage model for this entity set
var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.SelectMany(a => a.EntitySetMappings)
.First(s => s.EntitySet == entitySet);
var entitySetMappings = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace).Single().EntitySetMappings.ToList();
var mapping = GetMapping(entitySetMappings, metadata.GetItems(DataSpace.CSpace)
.Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType)
.Cast<EntityType>()
.Single(x => x.Name == entityType.Name));

// Find the storage entity set (table) that the entity is mapped
var mappingFragment = (mapping.EntityTypeMappings.FirstOrDefault(a => a.IsHierarchyMapping) ?? mapping.EntityTypeMappings.First()).Fragments.First();
var mappingFragment =
(mapping.EntityTypeMappings.FirstOrDefault(a => a.IsHierarchyMapping) ??
mapping.EntityTypeMappings.First()).Fragments.First();

entityMap.ModelType = entityType;
entityMap.ModelSet = entitySet;
Expand All @@ -90,22 +85,40 @@ public EntityMap GetEntityMap(Type type, ObjectContext objectContext)
SetTableName(entityMap);

// set properties
SetProperties(entityMap, mappingFragment);
SetProperties(entityMap, mapping, type);

// set keys
SetKeys(entityMap);

return entityMap;
}

private static EntitySetMapping GetMapping(List<EntitySetMapping> entitySetMappings, EntityType entitySet)
{
var mapping = entitySetMappings.SingleOrDefault(x => x.EntitySet.Name == entitySet.Name);
if (mapping != null)
{
return mapping;
}
mapping = entitySetMappings.SingleOrDefault(
x => x.EntityTypeMappings.Where(y => y.EntityType != null).Any(y => y.EntityType.Name == entitySet.Name));
if (mapping != null)
{
return mapping;
}
return entitySetMappings.Single(x => x.EntityTypeMappings.Any(y => y.IsOfEntityTypes.Any(z => z.Name == entitySet.Name)));
}

private static void SetKeys(EntityMap entityMap)
{
var modelType = entityMap.ModelType;
foreach (var edmMember in modelType.KeyMembers)
{
var property = entityMap.PropertyMaps.FirstOrDefault(p => p.PropertyName == edmMember.Name);
if (property == null)
{
continue;
}

var map = new PropertyMap
{
Expand All @@ -116,12 +129,46 @@ private static void SetKeys(EntityMap entityMap)
}
}

private static void SetProperties(EntityMap entityMap, MappingFragment mappingFragment)
private static IEnumerable<Type> GetParentTypes(Type type)
{
foreach (var propertyMapping in mappingFragment.PropertyMappings)
// is there any base type?
if ((type == null) || (type.BaseType == null))
{
var map = new PropertyMap();
map.PropertyName = propertyMapping.Property.Name;
yield break;
}

// return all implemented or inherited interfaces
foreach (var i in type.GetInterfaces())
{
yield return i;
}

// return all inherited types
var currentBaseType = type.BaseType;
while (currentBaseType != null)
{
yield return currentBaseType;
currentBaseType = currentBaseType.BaseType;
}
}

private static void SetProperties(EntityMap entityMap, EntitySetMapping mapping, Type type)
{
var isTypeOf = new HashSet<string>(GetParentTypes(type).Union(new[] {type}).Select(o => o.Name));

foreach (var propertyMapping in
mapping.EntityTypeMappings.Where(
o => o.EntityTypes == null || o.EntityTypes.Count < 1 ||
o.EntityTypes.Any(et => isTypeOf.Contains(et.Name)))
.SelectMany(o => o.Fragments)
.SelectMany(o => o.PropertyMappings)
//.Where(o => o.Property.DeclaringType.)
.GroupBy(o => o.Property.Name).Select(o => o.First()))
{
var map = new PropertyMap
{
PropertyName = propertyMapping.Property.Name
};

entityMap.PropertyMaps.Add(map);

Expand All @@ -136,7 +183,7 @@ private static void SetProperties(EntityMap entityMap, MappingFragment mappingFr
var complexPropertyMapping = propertyMapping as ComplexPropertyMapping;
}
}

private static void SetTableName(EntityMap entityMap)
{
var builder = new StringBuilder(50);
Expand All @@ -151,21 +198,33 @@ private static void SetTableName(EntityMap entityMap)

storeSet.MetadataProperties.TryGetValue("Table", true, out tableProperty);
if (tableProperty == null || tableProperty.Value == null)
storeSet.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Table", true, out tableProperty);
{
storeSet.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Table",
true, out tableProperty);
}

if (tableProperty != null)
{
table = tableProperty.Value as string;
}

// Table will be null if its the same as Name
if (table == null)
{
table = storeSet.Name;
}

storeSet.MetadataProperties.TryGetValue("Schema", true, out schemaProperty);
if (schemaProperty == null || schemaProperty.Value == null)
storeSet.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Schema", true, out schemaProperty);
{
storeSet.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Schema",
true, out schemaProperty);
}

if (schemaProperty != null)
{
schema = schemaProperty.Value as string;
}

if (!string.IsNullOrWhiteSpace(schema))
{
Expand All @@ -182,6 +241,5 @@ private static string QuoteIdentifier(string name)
{
return ("[" + name.Replace("]", "]]") + "]");
}

}
}
}

0 comments on commit 75989b9

Please sign in to comment.