Entity Framework Code First: How can I determine the foreign key property used for a navigation property at runtime?

前端 未结 2 542
礼貌的吻别
礼貌的吻别 2021-02-04 18:39

I have an Entity Framework Code First DbContext with the following entities configured. In this example class Bar is a child of class Foo.

public class Foo
{
            


        
2条回答
  •  耶瑟儿~
    2021-02-04 19:17

    I was actually able to determine the foreign key properties by using the GetDependentProperties method of the NavigationProperty class.

    Here is the code that I used (more or less) to get what I needed:

    object[] GetForeignKeyPropertyValues(TEntity entity, Expression> navigationProperty)
    {
        if (entity == null)
            return new object[] { };
    
        // Find the entity metadata in the object context.
        // (Assume you have access to the DbContext through the property CurrentDbContext.)
        var objectContext = (CurrentDbContext as IObjectContextAdapter).ObjectContext; 
    
        var metadataNamespace = ObjectContextAdapter.GetType().Namespace;
    
        var entityIdentity = metadataNamespace + "." + typeof(TEntity).Name; // HACK: This seems to work to retrieve the EntityType for an entity.
        var entityMetadata = objectContext.MetadataWorkspace.GetItem(entityIdentity, DataSpace.CSpace);
    
        // TODO: Verify that the entity metadata was found.
    
        // Get the navigation property metadata by parsing the name from the navigation property expression.
        var navigationPropertyName = GetPropertyName(navigationProperty);
        var navigationPropertyMetadata = entityMetadata.NavigationProperties.FirstOrDefault(np => np.Name == navigationPropertyName);
    
        // TODO: (JMB) Verify that the navigation property metadata was found.
    
        // Extract the foreign key columns from the navigation property.
        var foreignKeyPropertyMetadatas = navigationPropertyMetadata.GetDependentProperties();
    
        // Create property getters for each foreign key property.
        var foreignKeyPropertyGetters = foreignKeyPropertyMetadatas
            .Select(propertyMetadata => MakePropertyGetter(propertyMetadata.Name))
            .ToArray();
    
        // Execute the foreign key property getters to get the foreign key property values for the specified entity.
        var foreignKeyPropertyValues = foreignKeyPropertyGetters
            .Select(propertyGetter => propertyGetter(entity))
            .ToArray();
    
        return foreignKeyPropertyValues;
    }
    
    static string GetPropertyName(Expression> navigationProperty)
    {
        var lambda = navigationProperty as LambdaExpression;
        var member = lambda.Body as MemberExpression;
    
        return member.Member.Name;
    }
    
    static Func MakePropertyGetter(Type entityType, string propertyName)
    {
        var parameterExpression = Expression.Parameter(typeof(TEntity), "entity");
        var propertyExpression = Expression.PropertyOrField(parameterExpression, propertyName);
    
        var lambdaExpression = Expression.Lambda(propertyExpression, parameterExpression);
        var lambdaFunction = lambdaExpression.Compile();
    
        return (Func)lambdaFunction;
    }
    

提交回复
热议问题