Interroger dynamiquement les entités d'Entity Framework pour les associer à l'entité principale

c# dynamic-queries entity-framework expression-trees reflection

Question

Je sais que le titre n’était pas le meilleur, mais voici ce que je veux réellement accomplir.

J'ai une vue de détails qui représente Entity1 et ses associations. Je capture les noms de propriété et les valeurs dans une paire clé / valeur. J'utilise actuellement la réflexion pour définir les propriétés d'entité sur les valeurs correspondantes pour les non associations. Je doute que ce soit le moyen le plus efficace, mais je n’ai pas trouvé de meilleur moyen d’utiliser les arbres d’expression. Alors maintenant, je dois définir les associations de Entity1 sur leurs entités correspondantes en fonction de la clé primaire de ces associations d'entités, appelez-les Entity2-4.

Lors de l'itération des propriétés de Entity1, je ne sais pas comment construire une requête dynamique sur Entity2-4 et définir Entity1.association sur l'entité correspondante. Voici le code que j'ai jusqu'à présent:

foreach (string k in e.Values.Keys)
{
    if (e.Values[k] != null && !String.IsNullOrEmpty(e.Values[k].ToString()))
    {
        System.Type objectType = Entity1.GetType();
        PropertyInfo[] p = objectType.GetProperties();

        foreach (PropertyInfo pi in p)
        {
            // set Entity1.Property for non associations (works just fine)
            if (pi.Name == k)
            {
                System.Type t = pi.PropertyType;
                pi.SetProperty(e.Values[k].ToString(), Entity1);
                break;
            }
            // when i see pi.Name contain Reference, I know I'm working on an association
            else if (pi.Name.Contains("Reference"))
            {
                // k is in the form of Entity.Property
                var name = pi.Name.Left("Reference");
                var keys = k.Split('.');
                var ent = keys[0];
                var prop = keys[1];
                if (name == ent)
                {
                    // here I need to obtain an instance from the db
                    // ie generate my dynamic query to the Entity with the name
                    // contained within the var "ent"

                    // I tried using reflection and could instantiate the entity 
                    // but it did me no good as I needed the entity from the db

                    var entityInstance = some dynamic query;

                    // here I need to set the association of Entity1 to entityInstance from above
                    // normally I would use reflection, but I'm not sure that would work
                    // since EntityReference is the actual property returned by reflection
                    Entity1.SetAssocation(prop, Entity2);
                    break;
                }
            }
        }
    }
}

MODIFIER

J'ai essentiellement besoin de construire l'entité et ses entités d'association afin de pouvoir les soumettre au contexte de données. Les entités 2 à 4 existent dans la base de données, je dois interroger la base de données pour obtenir les instances auxquelles je peux les associer à la nouvelle entité 1 que je crée et que je vais soumettre.

Mon modèle de base:

Entité1

Entity1.ID
Entity1.Prop1
Entity1.Prop2
Entity1.Prop3
Entity1.Entity2
Entity1.Entity3
Entity1.Entity4

Entity2

Entity2.ID
Entity2.Name

Entity3

Entity3.ID
Entity3.Name

Entity4

Entity4.ID
Entity4.Name

Réponse populaire

Nous avons eu une discussion approfondie sur la façon d'extraire les metadata de DbContext . Voici quelques liens pour vous aider à démarrer. Et je vais ajouter quelques commentaires spécifiques.

Comment puis-je lire les métadonnées EF DbContext par programme?

Un bref résumé (mais vous devriez en vérifier plus):

using (var db = new MyDbContext())
{
    var objectContext = ((IObjectContextAdapter)db).ObjectContext;
    var container = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace);

    var dependents = ((EntitySet)(set)).ForeignKeyDependents;
    var principals = ((EntitySet)(set)).ForeignKeyPrincipals;
    var navigationProperties = ((EntityType)(set.ElementType)).NavigationProperties;

    // and e.g. for many-to-many (there is more for other types)
    ManyToManyReferences = navigationProperties.Where(np =>
        np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many &&
        np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
        .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
        .ToList();
}

@Goran Obradovic a fait un excellent travail en résumant ce que j'ai commencé dans une série de requêtes réutilisables (mes remerciements lui reviennent :).

J'ai élaboré toutes les autres informations qui y figurent. Ceci concerne uniquement le DataSpace.CSpace (qui vous est le plus utile), mais il existe également DataSpace.SSpace etc. - qui sont plus adaptés à la création de requêtes SQL, etc.


Détails:
Dans votre cas, ce qui suit pourrait être utile:
(note: je ne suis pas tout à fait sûr de ce que vous cherchez, mais j'essaie de guess quelle direction vous allez)

db.Set<Worker>().Find(1);

Méthode générique permettant d'accéder à DbSet pour une entité spécifique.

Vous pouvez également le construire à partir d'un Type si vous souhaitez qu'il soit entièrement dynamique, par exemple ...
(J'ai toujours voulu faire ça :)

MethodInfo setMethod = typeof(DbContext).GetMethod("Set", new Type[]{});
MethodInfo genericSetMethod = setMethod.MakeGenericMethod(new Type[] { typeof(YourEntity) });
var set = genericSetMethod.Invoke(db, new object[] {});  

Mettez votre entité - ou votre Type place de typeof(YourEntity) .

Vous pouvez ensuite poursuivre et interroger cela, par exemple, Find(id) - pour cette entité - pour obtenir des valeurs concrètes, etc.

C'est aussi dynamique que possible - je ne sais pas si c'est ce que vous voulez - mais je ne fais que lancer des choses ici au cas où vous en auriez besoin.

Cela devrait vous permettre de commencer au moins, j'espère.


liens:
(tous sont mes postes - certains peuvent être plus ou moins pertinents mais pourraient aider)
Comment puis-je lire les métadonnées EF DbContext par programme?
Comment vérifier par test unitaire que les propriétés marquent comme calculé dans le modèle ORM?
Demander au schéma de modèle de créer une base de données par programme à l'aide d'un fournisseur qui ne prend pas en charge CreateDatabase
Transformation de données programmatiques dans la migration EF5 Code First




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi