我如何通过编程读取EF DbContext元数据?

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

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

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

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

戈兰,这应该让你开始…
(我没有玩过多less东西 – 在debugging器中试验一下,看看哪些属性/信息以及如何获取它)

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

其中一些属性似乎不会暴露于“普通公众”,所以您需要使用reflection – 或find一些更聪明的方式 – 但是有很多信息在里面。



和一些更多的信息在这些链接…

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

如何提取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方法不是我的礼貌,学分转到Jon Skeet,代码是在这个答案的帮助下创build的

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