9

Does anyone know how one goes about obtaining the schema information out of an edmx generated Entity Framework?

Specifically I want to manage to traverse the foreign key for an entity that I don't currently have an instance of and get the it's foreign key relationships, and I want to do this via reflection in a way that'll be generically applied to any entity class without custom code each time.

EG: My schema has 2 classes, User and Group. I have the number "42" that I know came from the "GroupId" property of a "User" entity, but at the moment I can't work out how to detect that this "GroupId" property of "User" foreign keys to the "Group" entity by it's "GroupId" property.

fyjham
  • 7,004
  • 2
  • 32
  • 40

2 Answers2

24

You can use the following approach --

foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
foreach (var entityMember in entity.NavigationProperties)
foreach (System.Data.Metadata.Edm.EdmProperty foreignKey in entityMember.GetDependentProperties())
{
    //... use foreignKey
}
Ashraf Alam
  • 3,500
  • 32
  • 31
9

Ended up finding the solution to this. The relevant information can be found in the context's RelationshipManager property. By calling GetAllRelatedEnds() and then finding the ones of the type AssociationSet.

The ElementType of the association set then contains an IsForeignKey property and also an array ReferentialConstraints that has properties for each constraint ToRole, ToProperty, FromRole and FromProperty respectively, and the RelationshipMultiplicity on the ToRole/FromRole can be used to determine the direction of the foreign key relationship.

Taking all this data and using the context's GetObjectByKey method I was able to programatically traverse the foreign key relationships defined for a context without having the associated entity.

fyjham
  • 7,004
  • 2
  • 32
  • 40
  • 1
    I couldn't get this to work. I couldn't find a RelationshipManager property on the context (though I can get it by CType(tableObject, IEntityWithRelationships).RelationshipManager), and then after doing that I couldn't find results from GetRelatedEnds that could be cast to AssociationSet. A code example would be deeply appreciated. – pbristow Nov 17 '11 at 14:34
  • 1
    Hey, apologies for the delayed response - I hadn't read this in a long time. I should have been more clear that I was working from an ObjectStateEntry as opposed to directly from the Context. The exact syntax I used from there was "foreach (AssociationSet assoc in ose.RelationshipManager.GetAllRelatedEnds().Select(end => end.RelationshipSet).Where(rs => rs is AssociationSet && ((AssociationSet)rs).ElementType.IsForeignKey).Cast())", then I had some additional logic to work out which side it was on cause I only wanted specific multiplicities of foreign keys. – fyjham Feb 06 '12 at 00:28