Add object to Entity Framework dynamically using Reflection

c#, entity-framework, system.reflection

Solution

If you want to use reflection and to find given entity by ID then, if ID is primary key this is fairly simple as this is all you have to do:

object entity = context.Set(domainObject.GetType()).Find(id);

If your property is not primary key then you need to do it as follows:

ParameterExpression p = Expression.Parameter(domainObject.GetType());
Expression property = Expression.Property(p, "ID");
Expression c = Expression.Constant(id);
Expression body = Expression.Equal(property, c);
Expression exp = Expression.Lambda(body, new ParameterExpression []{ p });

MethodInfo singleMethod = typeof(Queryable).GetMethods()
    .Single(m => m.Name == "Single" && m.GetParameters().Count() == 2)
    .MakeGenericMethod(domainObject.GetType());

DbSet dbSet = context.Set(domainObject.GetType());
object entity = singleMethod.Invoke(null, new object[]{ dbSet, exp });

First with `Expression` class you build expression that will be passed to `Single` method (in your case this will be `p => p.ID == id`). Then you search proper `Single` method from `Queryable` class. The last thing is to invoke this method with proper parameters. This way you may do any linq queries with use of `Reflection`.

Problem

In the following code, the type of `domainObject` varies (but ends with `DO`, which I trim then to get the corresponding table name). Having the name of the table and its type, I want to update an existing object - its name is the same as the `tableName` due to the EF - in the database with the new property values from `domainObject`. Therefore, I have to find the POCO in the table with the same `ID` first to overwrite this. This is the code so far: ``` public void Update(object domainObject) { Type type = domainObject.GetType(); string tableName = type.Name.Substring(0, type.Name.Length - 2); PropertyInfo tableProp = typeof(MyDbContext).GetProperty(tableName); Type tableType = tableProp.PropertyType; Type pocoType = tableType.GetGenericArguments()[0]; int id = (int)type.GetProperty("ID").GetValue(domainObject); using (var context = new MyDbContext()) { object table = tableProp.GetValue(context); MethodInfo singleMethod = tableType.GetMethod("Single"); } } ``` Usually, knowing the actual table and not just its type, I would now get the POCO via ``` var poco = context.TableName.Single(item => item.ID == id); ``` There's 2 problems here: (1) `Single` is an extension method. (2) I don't have an idea how to get the lambda expression in form of an `object` to pass it to the `Invoke` of `Single`. Is there any way to do this at all with Reflection, or do I have to work around this? (For example, I could iterate through the items in `table` and check manually [which would load everything from the DB into memory and thus should be avoided], or maybe configure the EF to do some kind of 'override' whenever I just `Add` and object whose `ID` is already present if this is possible). Even supposing I could work around this, I'd still like to know a definitive answer to this question, since it's pretty interesting for me!

Original source

Related problems