Jaylen
Jaylen

Reputation: 40289

How to get a list of all Entity relation in Entity Framework 6.1?

I am trying to get a list of all relations "foreign keys" on a model programmatically (key, related object, foreign column name.)

I found this other question which seems to be doing the same thing. But I am unable to get the code in the answer to work for me.

Here is what I have done

    public List<string> GetObjectRelations(Type type)
    {

        var metadata = ((IObjectContextAdapter)this.context).ObjectContext.MetadataWorkspace;

        // Get the part of the model that contains info about the actual CLR types
        var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));

        var fk = metadata.GetItems<AssociationType>(DataSpace.CSpace).Where(a => a.IsForeignKey);

        //check if the table has any foreign constraints for that column
        var fkname = fk.Where(x => x.ReferentialConstraints[0].ToRole.Name == type.Name).Where(x => x.ReferentialConstraints[0].ToProperties[0].Name == type.Name);

        //Get the corresponding reference entity column name
        return fkname.Select(x => x.ReferentialConstraints[0].FromProperties[0].Name).ToList();

    }

Here is how I call this method

var relations = QueryExtractor.GetObjectRelations(typeof(TSource)); 

But this code is not working for me. The return value is empty.

How can I correctly get the foreign key and the object that they are are related to?

UPDATED

Here is my current code based on muratgu answer below. But it is still now giving me a list of the relations

    public List<Dictionary<string, object>> GetObjectRelations(Type type)
    {
        var relations = new List<Dictionary<string, object>>();

        var metadata = ((IObjectContextAdapter)this.context).ObjectContext.MetadataWorkspace;

        var fk_all = metadata.GetItems<AssociationType>(DataSpace.CSpace).Where(a => a.IsForeignKey);

        var fk_out = fk_all.Where(x => x.ReferentialConstraints[0].ToRole.Name == type.Name).ToList(); // relations going out 

        foreach (var fk in fk_out)
        {
            var relation = new Dictionary<string, object>();

            var fk_ref = fk.ReferentialConstraints[0]; //How can a foreign key relation have more than one column?

            var objectName = fk_ref.FromRole.Name;

            var attributeName = fk_ref.FromProperties[0].Name;

            relation.Add(objectName, attributeName);

            relations.Add(relation);
        }

        return relations;
    }

Upvotes: 2

Views: 3667

Answers (2)

muratgu
muratgu

Reputation: 7311

You already had everything you need in your snippet of code, although I have a hunch that returning a list of strings is not going to be enough for you. I will break it down, so you can decide what to do with the results.

        // assume Child has a foreign key (Parent_Id) to Parent (Id)
        // assume primary keys are not composite
        var type = typeof(Child); 
        var fk_all = metadata.GetItems<AssociationType>(DataSpace.CSpace).Where(a => a.IsForeignKey);
        var fk_out = fk_all.Where(x => x.ReferentialConstraints[0].ToRole.Name == type.Name).ToList(); // relations going out 
        foreach(var fk in fk_out) { // could be many
            var fk_ref = fk.ReferentialConstraints[0]; // what if more than one?
            Console.WriteLine("From {0} - {1} ", fk_ref.FromRole.Name, fk_ref.FromProperties[0].Name);
            Console.WriteLine("To {0} - {1} ", fk_ref.ToRole.Name, fk_ref.ToProperties[0].Name);
        }

Assuming Child has a foreign key Parent_Id to Parent (Id), this will print:

        From Parent - Id
        To Child - Parent_Id

Upvotes: 1

poppertech
poppertech

Reputation: 1294

Based on this answer, you can use the Entity Framework Mapping Api Extensions. For example, the following line retrieves the foreign keys for the Product type:

string[] fks = context.Db<Product>().Fks.Select(fk => fk.PropertyName).ToArray();

Upvotes: 0

Related Questions