How I can read EF DbContext metadata programmatically?
Gorane, this should get you started...
(I haven't played much with it - it takes a bit of experimenting in the debugger to see which properties / info and how to get it)
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();
}
and more specifically...
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;
}
}
Some of these properties seem to not be exposed to 'general public' so you'd need to use reflection - or find some smarter way - but a good deal of info is in there.
And some more info in these links...
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?
EDIT: Using your list of navigationProperties as starting point, I got everything I needed like this:
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 method is not my courtesy, credits go to Jon Skeet, code was created with help of this answer
Here is my CreateLambdaExpression method:
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});
}
Related videos on Youtube
Goran Obradovic
Responsible coder. #SOreadytohelp Blogger, husband and father at home. Freelancing software consultant based in Nuremberg. Amateur shutterbug elsewhere :) ###More about me: CV | LinkedIn | Twitter
Updated on September 15, 2022Comments
-
Goran Obradovic over 1 year
I have application which uses EF-CodeFirst 5 (dll ver 4.4.0.0, on .net 4.0).
I need to be able to read entity metadata, so that I can, for a given entry type get following information:
- which properties are one-many relations (referenced entities)
- which properties are many-one relations (collections of entities referencing current one)
- also nice but not absolutely necessary: which properties are many-many relations (collections of relations)
I can get this info by writing foreach loops on lists of properties and then "recognizing" them by relying on all of the references being virtual, but I feel that is not "proper" way. I know that
EdmxWriter
can provide that information in xml format, but it does so by accessing InternalContext which is not publicly accessible and I want to get strongly typed lists/arrays directly, without using that xml. Which API should I use (if there is one for this, it seems that I cannot find it)?-
Jonathan Stark over 10 yearsThere are now plans to improve the Metadata API: entityframework.codeplex.com/workitem/1471 More here: romiller.com/2013/09/24/…
-
Goran Obradovic about 11 yearsThanks, this got me started, and I got what I need (without reflexion), expanded your answer to show how.
-
NSGaga-mostly-inactive about 11 yearsthat's great, thank you too - I'm going to keep this in my links - I had a few uses for that before - but never did 'elaborate' on that in too many details, this is very helpful piece of code. And a good question.
-
Kirk Woll over 9 yearsIt seems that
ForeignKeyDependents
andForeignKeyPrincipals
is markedinternal
inEntitySet
for EF6. -
InteXX about 9 years@GoranObradovic: What purpose does
CreateLambdaExpression
serve here? If you just want filtered lists ofNavigationProperties
, is it needed at all? If I could see the expression tree you ended up with I'd be able to understand it better. Could you edit the answer again to include the finalCreateLambdaExpression
code you ended up with? It's still unclear to me. Thanks. -
Goran Obradovic about 9 years@InteXX answer already had link to another answer that gave me that method, but I included my simplified version I ended up using, it is just selector for property with given name. Anyway, try to use newer EF versions, this one sucks :)
-
InteXX about 9 years@GoranObradovic: I would absolutely LOVE to do this with my current EF6.1 DbContext. I thought this was the way to work Metadata with 6.1. Apparently not? I'm not finding documentation.
-
InteXX about 9 years@GoranObradovic: Got it, thanks. In fact I've been using some of that. Here's what I'm trying to do.
-
Rudey about 5 yearsInstead of finding the primary key, or navigation properties, is there a way to figure out which properties have (unique) indexes on them?