我如何编程读取EF的DbContext元?(How I can read EF DbContext

2019-08-18 08:11发布

我有应用程序,它采用EF-CodeFirst 5(DLL版本4.4.0.0,上.NET 4.0)。

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

  • 其性质是一个一对多的关系(引用的实体)
  • 其性能有很多,一个关系(参考当前实体的集合)
  • 还不错,但不是绝对必要的:其性质是多对多的关系(关系的集合)

我可以通过在属性列表写foreach循环,然后依靠所有引用是虚拟的“承认”他们得到这个信息,但我觉得不是“正确”的方式。 我知道EdmxWriter可以提供XML格式的信息,但通过访问InternalContext这是不能公开访问这样做,我想直接获得强类型列表/阵列,而不使用XML。 我应该使用哪种API(如果有这个,我似乎无法找到它)?

Answer 1:

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

某些属性似乎不是被暴露在“公众”,所以你需要使用反射 - 或找一些更聪明的方式 - 但信息的一个很好的协议是在那里。



而在这些链接的一些详细信息...

如何获得第一的EntityKey名称为实体EF4

我怎样才能提取数据库表和列名上EF4实体的属性?


编辑 :使用您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方法是不是我的客套话,学分去乔恩斯基特,代码用的帮助下创建这个答案

这里是我的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});
}


文章来源: How I can read EF DbContext metadata programmatically?