0

I am trying to get all entities (models) and then their navigational properties which are of type ICollection only, but it doesn't seem to be working. This is what I tried so far:

foreach (var propertyInfo in new CompanyDBContext().GetType()
                    .GetProperties(
                            BindingFlags.Public
                            | BindingFlags.Instance))
{
    Console.WriteLine(propertyInfo.Name);

    //var entity = DbSet<propertyInfo.Name>
}

I am able to get all models I have using code above, but how can I get all navigational properties which are of type ICollection next?

CarenRose
  • 1,266
  • 1
  • 12
  • 24
Mathematics
  • 7,314
  • 25
  • 77
  • 152
  • This has been asked before, here: http://stackoverflow.com/questions/17886725/ef5-how-to-get-list-of-navigation-properties-for-a-domain-object – Wicher Visser Apr 14 '16 at 08:34
  • @WicherVisser yes, but they already have entities, where as I have propertyInfo, I am not sure how can I convert propertyInfo into objects, I am also not sure how to select ICollections only – Mathematics Apr 14 '16 at 08:36
  • Creating an instance of a type using PropertyInfo has also been done before: http://stackoverflow.com/questions/15641339/create-new-propertyinfo-object-on-the-fly – Wicher Visser Apr 14 '16 at 08:39

1 Answers1

1

You have to first get type of all entities from DbContext. Any property of type DbSet<> defined within DbContext is actually enclosing an entity. You need to grab that instead.

private static readonly Type DbSetType = typeof(DbSet<>);
private static IEnumerable<Type> GetAllEntityTypes(Type contextType)
{
    return contextType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .Select(p => p.PropertyType)
        .Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == DbSetType)
        .Select(t => t.GetGenericArguments()[0]);
}

And to get Navigation properties from Entity type, here is a helper method that is modified version of https://stackoverflow.com/a/27124251/2509344

private static readonly MethodInfo CreateObjectSetMethodInfo = typeof(ObjectContext).GetMethod("CreateObjectSet", new Type[0]);
private static readonly Type CollectionType = typeof(ICollection<>);
private static IEnumerable<PropertyInfo> GetNavigationProperties(DbContext context, Type entityType)
{
    var objectContext = ((IObjectContextAdapter)context).ObjectContext;
    var createObjectSetMethod = CreateObjectSetMethodInfo.MakeGenericMethod(entityType);
    var entity = createObjectSetMethod.Invoke(objectContext, new object[0]);

    var entitySet = (EntitySet)entity.GetType().GetProperty("EntitySet").GetValue(entity);
    var elementType = entitySet.ElementType;
    return elementType.NavigationProperties.Select(p => entityType.GetProperty(p.Name))
        // Filter Properties that are of type ICollection
        .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == CollectionType);
}

And to finally get all navigation properties of entities defined inside DbContext:

var context = new CompanyDBContext();
var entities = GetAllEntityTypes(context.GetType());
foreach (var entity in entities)
{
    var navigationProperties = GetNavigationProperties(context, entity).ToList();
}
Community
  • 1
  • 1
Adnan Umer
  • 3,669
  • 2
  • 18
  • 38