2

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;
    }
Community
  • 1
  • 1
Jaylen
  • 39,043
  • 40
  • 128
  • 221
  • Let's say `Entity2` has a foreign key called `Fk1` that points to `Entity1`.`Id`, what do you want to see on that list? – muratgu Jun 28 '16 at 23:40
  • I want to see the foreign key "i.e ClientId" and I also want to know the object that it points to "i.e "Client" and I want to know the remote key "i.e Id" – Jaylen Jun 29 '16 at 00:06

2 Answers2

1

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
muratgu
  • 7,241
  • 3
  • 24
  • 26
  • Thank you for this. I apologize it took me a while to be able to test it. The fk_all returns one object but the fk_out line returns 0 records. I will update my question now with my recent code – Jaylen Jul 01 '16 at 15:02
0

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();
Community
  • 1
  • 1
poppertech
  • 1,286
  • 2
  • 9
  • 17