Dynamically query entities from Entity Framework for association to primary Entity

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

Question

I know the title wasn't the greatest, but here is what I actually want to accomplish.

I have a details view that represents Entity1 and its associations. I am capturing the property names and values in a key/value pair. I am currently using reflection to set the Entity properties to the corresponding values for non associations. I doubt this is the most efficient way, but I have been unable to find a better way using Expression Trees. So now I need to set the associations of Entity1 to their corresponding entities based on the primary key of those entity associations, call them Entity2-4.

When iterating the Properties of Entity1, I don't know how to construct a dynamic query to Entity2-4 and set Entity1.association to the corresponding entity. Here is the code I have so far:

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

EDIT

I basically need construct the entity and its association entities so that I can submit them to the data context. Entity 2 through 4 exist in the db, I need to query the db to obtain the instances to that I may associate them to the new Entity1 I am creating and going to submit.

My basic model:

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

Popular Answer

We've had an in-depth discussion about how to get the metadata out of the DbContext. Here are a few links to get you started. And I'll add some specific comments.

How I can read EF DbContext metadata programmatically?

A short summary (but you should check in there for more):

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 did a great job to wrap up what I started into a set of reusable queries (my due credits to him:).

I have worked out all other sorts of information that's in there. This is just for the DataSpace.CSpace (which is the most useful to you), but there is also DataSpace.SSpace etc. - which are more for creating SQL queries etc. I'll put most links at the bottom.


Specifics:
In your case following might be helpful:
(note: I'm not entirely sure what you're after, but I'm trying to guess here what's the direction that you're heading)

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

Is the generic method for accessing DbSet for a specific entity.

You could also construct it from a Type if you need it to be fully dynamic, e.g....
(I always wanted to do this:)

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

Put your entity - or your Type instead of typeof(YourEntity).

You could then proceed and query that for e.g. Find(id) - for that entity - to get concrete values etc.

That's as dynamic as it gets - I'm not sure if that's what you want - but I'm just throwing things out here in case you need it.

That should get you started at least I hope.


links:
(all are posts of mine - some may be more or less relevant but might help)
How I can read EF DbContext metadata programmatically?
How check by unit test that properties mark as computed in ORM model?
Get Model schema to programmatically create database using a provider that doesn't support CreateDatabase
Programmatic data transformation in EF5 Code First migration



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why