Consultar dinámicamente las entidades desde Entity Framework para su asociación con la entidad primaria

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

Pregunta

Sé que el título no fue el mejor, pero esto es lo que realmente quiero lograr.

Tengo una vista de detalles que representa a Entity1 y sus asociaciones. Estoy capturando los nombres y valores de las propiedades en un par clave / valor. Actualmente estoy usando la reflexión para establecer las propiedades de la entidad en los valores correspondientes para no asociaciones. Dudo que esta sea la forma más eficiente, pero no he podido encontrar una mejor manera de usar los árboles de expresión. Así que ahora necesito establecer las asociaciones de Entity1 en sus entidades correspondientes según la clave principal de esas asociaciones de entidades, llámenlas Entity2-4.

Al iterar las propiedades de Entity1, no sé cómo construir una consulta dinámica para Entity2-4 y establecer Entity1.association para la entidad correspondiente. Aquí está el código que tengo hasta ahora:

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

EDITAR

Básicamente necesito construir la entidad y sus entidades de asociación para poder enviarlas al contexto de datos. La entidad 2 a 4 existe en la base de datos, necesito consultar la base de datos para obtener las instancias a las que puedo asociarlas a la nueva entidad1 que estoy creando y que voy a enviar.

Mi modelo básico:

Entidad1

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

Entidad2

Entity2.ID
Entity2.Name

Entidad 3

Entity3.ID
Entity3.Name

Entidad 4

Entity4.ID
Entity4.Name

Respuesta popular

Hemos tenido una discusión en profundidad sobre cómo obtener los metadata del DbContext . Aquí hay algunos enlaces para empezar. Y voy a añadir algunos comentarios específicos.

¿Cómo puedo leer metadatos EF DbContext mediante programación?

Un breve resumen (pero debe registrarse para más):

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 hizo un gran trabajo para resumir lo que comencé en un conjunto de consultas reutilizables (mis debidos créditos para él :).

He resuelto todo otro tipo de información que está ahí. Esto es solo para DataSpace.CSpace (que es el más útil para usted), pero también hay DataSpace.SSpace etc., que son más para crear consultas SQL, etc. Pondré la mayoría de los enlaces en la parte inferior.


Detalles específicos:
En su caso, lo siguiente puede ser útil:
(nota: no estoy del todo seguro de lo que está buscando, pero estoy tratando de guess cuál es la dirección hacia la que se dirige)

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

Es el método genérico para acceder a DbSet para una entidad específica.

También puede construirlo a partir de un Type si necesita que sea completamente dinámico, por ejemplo ...
(Siempre quise hacer esto :)

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

Coloque su entidad - o su Type lugar de typeof(YourEntity) .

Luego puede proceder y consultar que, por ejemplo, Find(id) - para esa entidad - para obtener valores concretos, etc.

Eso es lo más dinámico posible. No estoy seguro de si eso es lo que quiere, pero solo estoy lanzando cosas aquí en caso de que las necesite.

Eso debería empezar, al menos espero.


campo de golf:
(todas son publicaciones mías, algunas pueden ser más o menos relevantes pero pueden ayudar)
¿Cómo puedo leer metadatos EF DbContext mediante programación?
¿Cómo verificar por unidad de prueba que las propiedades marcan como calculadas en el modelo ORM?
Obtenga el esquema del modelo para crear una base de datos mediante programación utilizando un proveedor que no es compatible con CreateDatabase
Transformación programática de datos en el código EF5 Primera migración



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow