entity-framework-4 - Entity Framework 代码优先 : How can I determine the foreign key property used for a navigation property at runtime?

标签 entity-framework-4 ef-code-first

我有一个 Entity Framework 代码优先 DbContext,配置了以下实体。在这个例子中,Bar 类是 Foo 类的一个子类。

public class Foo
{
    public Guid Id { get; set; }

    public virtual ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    public Guid Id { get; set; }

    public Guid FooId { get; set; }

    public virtual Foo Foo { get; set; }
}

现在我知道,在内部,Entity Framework 理解 Foo 和 Bar 之间的关系是由外键 Bar.FooId 定义的。我想做的是在运行时使用表达式以某种方式提取这种关系。我想实现一个行为如下的方法:
var context = new FooBarDbContext();
var bar = context.Set<Bar>().First();

// I want this method to return bar.FooId when passed the expression b => b.Foo
object result = MyService.GetForeignKeyValue(bar, b => b.Foo); 

现在在这个简单的例子中,我知道我可以得到 bar.FooId 并完成。关键是我正在编写一个类,我相信上面指定的 GetForeignKeyValue 方法是用户最干净的界面。

是否可以查询 DbContext 配置以确定哪个属性用作导航属性的外键? (假设有一个)

最佳答案

我实际上能够通过使用 GetDependentProperties 来确定外键属性。 NavigationProperty的方法类(class)。

这是我使用(或多或少)获得所需内容的代码:

object[] GetForeignKeyPropertyValues<TEntity, TRelatedEntity>(TEntity entity, Expression<Func<TEntity, TRelatedEntity>> 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<EntityType>(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<TEntity>(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<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> navigationProperty)
{
    var lambda = navigationProperty as LambdaExpression;
    var member = lambda.Body as MemberExpression;

    return member.Member.Name;
}

static Func<TEntity, object> MakePropertyGetter<TEntity>(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<TEntity, object>)lambdaFunction;
}

关于entity-framework-4 - Entity Framework 代码优先 : How can I determine the foreign key property used for a navigation property at runtime?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16442801/

相关文章:

asp.net-mvc - 多个 DbContext,多个 Database.SetInitializer

asp.net-mvc - 将 System.ComponentModel.DataAnnotations 与 Entity Framework 4.0 结合使用

c# - MVC3中相同类型实体之间的多对多关系

c# - EFCodeFirst : The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects

c# - 一对一或零对一 Entity Framework 代码优先 FluentApi

entity-framework - Entity Framework 迁移停止检测POCO更新

linq-to-sql - 现在已经发布Entity Framework 4.0了吗?转储Linq-To-Sql吗?

entity-framework-4 - 来自两个数据库的 Entity Framework 模型

c# - 如何将单个实体映射到多个表

.net - 添加迁移给出文件名已经存在