ef-code-first - 如何以编程方式读取EF DbContext元数据?

标签 ef-code-first metadata entity-framework-5

我有使用EF-CodeFirst 5(.net 4.0上的dll版本4.4.0.0)的应用程序。

我需要能够读取实体元数据,以便对于给定的条目类型,我可以获取以下信息:


哪些属性是一对多关系(引用实体)
哪些属性是多对一关系(引用当前关系的实体的集合)
也很好,但不是绝对必要的:哪些属性是多对多关系(关系的集合)


我可以通过在属性列表上编写foreach循环,然后依靠所有虚拟引用来“识别”它们来获取此信息,但是我觉得这不是“正确”的方式。我知道EdmxWriter可以xml格式提供该信息,但是它可以通过访问InternalContext来实现,而InternalContext不能公开访问,我想直接获取强类型列表/数组,而不使用该xml。我应该使用哪个API(如果有一个,似乎找不到)?

最佳答案

Gorane,这应该让您入门...
(我玩的不多-在调试器中需要进行一些实验才能看到哪些属性/信息以及如何获取它)

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();
}


更具体地说...

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;
    }
}


其中一些属性似乎并未向“公众”公开,因此您需要使用反射-或找到一些更聪明的方法-但其中包含大量信息。





在这些链接中还有更多信息...

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?



编辑:
使用您的navigationProperties列表作为起点,我得到了所需的一切:

        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方法不是我的礼貌,感谢Jon Skeet,代码是在this answer的帮助下创建的

这是我的CreateLambdaExpression方法:

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});
}

关于ef-code-first - 如何以编程方式读取EF DbContext元数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15718301/

相关文章:

azure - 是否可以在 azure 搜索中使用元数据作为自定义技能的输入?

entity-framework - 加载在另一个DbContext中所做的更改

performance - VS2012 中非常慢的 Entity Framework 模型设计器

c# - 多对多 self 加入 Entity Framework 代码优先

c# - 包含和选择在一起的 Entity Framework

c# - Entity Framework 代码优先关系映射问题

jquery - 关于 jQuery、元数据和 XHTML 合规性

c# - 指定的包含路径无效

python - 有没有办法从音频文件中删除/编辑名为 "tag"的元数据条目,而无需安装任何其他内容?

entity-framework - Entity Framework 代码优先 - 逆向工程师