Sto cercando di ottenere un elenco di tutte le relazioni "chiavi esterne" su un modello a livello di codice (chiave, oggetto correlato, nome di colonna esterna).
Ho trovato quest'altra domanda che sembra fare la stessa cosa. Ma non riesco a far funzionare il codice nella risposta per me.
Ecco cosa ho fatto
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();
}
Ecco come chiamo questo metodo
var relations = QueryExtractor.GetObjectRelations(typeof(TSource));
Ma questo codice non funziona per me. Il valore di ritorno è vuoto.
Come posso ottenere correttamente la chiave esterna e l'oggetto a cui sono collegati?
AGGIORNATO
Ecco il mio codice attuale basato sulla risposta di muratgu qui sotto. Ma mi sta ancora dando una lista delle relazioni
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;
}
Hai già tutto ciò che ti serve nel tuo snippet di codice, anche se ho la sensazione che restituire un elenco di stringhe non ti basterà. Lo analizzerò, in modo che tu possa decidere cosa fare con i risultati.
// 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);
}
Supponendo che Child
abbia una chiave Parent_Id
to Parent
( Id
), questo stamperà:
From Parent - Id
To Child - Parent_Id