Interrogare dinamicamente le entità da Entity Framework per l'associazione all'entità primaria

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

Domanda

So che il titolo non era il massimo, ma ecco quello che in realtà voglio realizzare.

Ho una vista dettagli che rappresenta Entity1 e le sue associazioni. Sto catturando i nomi e i valori delle proprietà in una coppia chiave / valore. Attualmente sto usando il reflection per impostare le proprietà Entity sui valori corrispondenti per le associazioni. Dubito che questo sia il modo più efficace, ma non sono riuscito a trovare un modo migliore di usare Expression Trees. Così ora ho bisogno di impostare le associazioni di Entità1 alle loro entità corrispondenti basate sulla chiave primaria di quelle associazioni di entità, chiamarle Entità2-4.

Quando si iterano le Proprietà di Entity1, non so come costruire una query dinamica su Entity2-4 e impostare Entity1.association sull'entità corrispondente. Ecco il codice che ho finora:

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;
                }
            }
        }
    }
}

MODIFICARE

Fondamentalmente ho bisogno di costruire l'entità e le sue entità di associazione in modo che possa inviarle al contesto dei dati. Le entità da 2 a 4 esistono nel db, ho bisogno di interrogare il db per ottenere le istanze a cui posso associarle alla nuova Entity1 che sto creando e che sto per inviare.

Il mio modello di base:

Entity1

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

Risposta popolare

Abbiamo avuto una discussione approfondita su come ottenere i metadata dal DbContext . Ecco alcuni link per iniziare. E aggiungerò alcuni commenti specifici.

Come posso leggere i metadati EF DbContext a livello di codice?

Un breve riassunto (ma dovresti controllare per saperne di più):

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 ha fatto un ottimo lavoro per concludere quello che ho iniziato in una serie di domande riutilizzabili (i miei crediti a lui dovuti :).

Ho elaborato tutti gli altri tipi di informazioni che sono lì dentro. Questo è solo per DataSpace.CSpace (che è il più utile per voi), ma c'è anche DataSpace.SSpace ecc. - che sono più utili per creare query SQL ecc. DataSpace.SSpace maggior parte dei collegamenti in fondo.


specifiche:
Nel tuo caso, seguire potrebbe essere utile:
(nota: non sono del tutto sicuro di cosa stai cercando, ma sto cercando di guess qui qual è la direzione che stai dirigendo)

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

È il metodo generico per accedere a DbSet per un'entità specifica.

Puoi anche costruirlo da un Type se ne hai bisogno per essere completamente dinamico, ad esempio ...
(Ho sempre voluto farlo :)

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

Metti la tua entità - o il tuo Type invece di typeof(YourEntity) .

Potresti quindi procedere e interrogare per es. Find(id) - per quell'entità - per ottenere valori concreti, ecc.

È così dinamico come non lo è - non sono sicuro che sia quello che vuoi - ma sto buttando qui le cose nel caso ne avessi bisogno.

Questo dovrebbe farti iniziare almeno, spero.


links:
(tutti sono post miei - alcuni potrebbero essere più o meno rilevanti ma potrebbero aiutare)
Come posso leggere i metadati EF DbContext a livello di codice?
Come verificare per unità di test che il marchio delle proprietà sia calcolato nel modello ORM?
Ottieni lo schema del modello per creare database in modo programmatico utilizzando un provider che non supporta CreateDatabase
Trasformazione dei dati programmatica nel codice EF5 Prima migrazione



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché