How I can read EF DbContext metadata programmatically?

后端 未结 1 534
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 14:49

I have application which uses EF-CodeFirst 5 (dll ver 4.4.0.0, on .net 4.0).

I need to be able to read entity metadata, so that I can, for a given entry type get fol

相关标签:
1条回答
  • 2020-11-27 15:26

    Gorane, this should get you started...
    (I haven't played much with it - it takes a bit of experimenting in the debugger to see which properties / info and how to get it)

    using (var db = new MyDbContext())
    {
        var objectContext = ((IObjectContextAdapter)db).ObjectContext;
        var container = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace);
        foreach (var set in container.BaseEntitySets)
        {
            // set.ElementType.
            foreach (var metaproperty in set.MetadataProperties)
            {
                // metaproperty.
            }
        }
    
        // ...or... 
    
        var keyName = objectContext
            .MetadataWorkspace
            .GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace)
            .BaseEntitySets
            .First(meta => meta.ElementType.Name == "Question")
            .ElementType
            .KeyMembers
            .Select(k => k.Name)
            .FirstOrDefault();
    }
    

    and more specifically...

    foreach (var set in container.BaseEntitySets)
    {
        var dependents = ((EntitySet)(set)).ForeignKeyDependents;
        var principals = ((EntitySet)(set)).ForeignKeyPrincipals;
        var navigationProperties = ((EntityType)(set.ElementType)).NavigationProperties;
        foreach (var nav in navigationProperties)
        {
            // nav.RelationshipType;
        }
    }
    

    Some of these properties seem to not be exposed to 'general public' so you'd need to use reflection - or find some smarter way - but a good deal of info is in there.



    And some more info in these links...

    How to get first EntityKey Name for an Entity in EF4

    How can I extract the database table and column name for a property on an EF4 entity?


    EDIT: Using your list of navigationProperties as starting point, I got everything I needed like this:

            ManyToManyReferences = navigationProperties.Where(np =>
                np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many &&
                np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
                .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
                .ToList();
    
            OneToManyReferences = navigationProperties.Where(np =>
                (np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
                np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne) &&
                np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
                .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
                .ToList();
    
            ManyToOneReferences = navigationProperties.Where(np =>
                np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many &&
                (np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
                np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne))
                .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
                .ToList();
    
            OneToOneReferences = navigationProperties.Where(np =>
                np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One &&
                np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One)
                .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
                .ToList();
    

    CreateLambdaExpression method is not my courtesy, credits go to Jon Skeet, code was created with help of this answer

    Here is my CreateLambdaExpression method:

    public static Expression<Func<TEntity, object>> CreateLambdaExpression<TEntity>(string propertyName)
    {
        ParameterExpression parameter = Expression.Parameter(typeof (TEntity), typeof (TEntity).Name);
        Expression property = Expression.Property(parameter, propertyName);
    
        return Expression.Lambda<Func<TEntity, object>>(property, new[] {parameter});
    }
    
    0 讨论(0)
提交回复
热议问题