0

I would like to save/update my changes in db with reflection. I just have name of a table and the id pk of the field. I try to update this table with reflection...

 var table =(IQueryable)dbContext.ctx
      .GetType()
      .GetProperty(tableName)
      .GetValue(dbContext.ctx, null);

First I have the table and with the Iqueryable I don't know how I can update my table in db.

Any help?

Thx

3 Answers 3

1

This answer is for a completeness of what you should do. Using Set (non-generic version) is the right approach. I know you just know the tableName (even the Type of your entity is not known). But Set requires a Type. So you need to find that type based on the PropertyType of the PropertyInfo you obtained from tableName. After obtaining a DbSet (non-generic), you can use all its methods without any more reflection. The entity passed in will be just object. Here is the detailed code:

//we don't check if tableName can be resolved successfully for simplicity
//NOTE that there should be only one generic argument
//We know it's a DbSet<T>, with this we should have T
var entityType = dbContext.ctx.GetType().GetProperty(tableName)
                          .PropertyType.GetGenericArguments()[0];
//now obtain an instance of DbSet normally
var entities = dbContext.ctx.Set(entityType);
//all methods of DbSet are available now although the arguments are 
//object (not strongly typed).
Sign up to request clarification or add additional context in comments.

Comments

1

Don't you need the DbSet<TEntity>?

var dbSet = (IDbSet<SomeEntity>)dbContext
                   .GetType()
                   .GetProperty(tableName, BindingFlags.Public | BindingFlags.Instance)
                   .GetValue(dbContext, null);

Now call DbSet<TEntity> methods as you would do it in a regular scenario, since you've a typed DbSet<T>.

A queryable won't help you much because as you've already guessed, it's about querying rather than performing write operations back to the database.

OP said...

I can't use DbSet because I never know the entity, I ve juste the name of the table. I make an back office for change value of reference table, an generic interface..

Then, your solution is going with reflection even to add the entities to the DbSet<TEntity>:

object dbSet = dbContext
                   .GetType()
                   .GetProperty(tableName, BindingFlags.Public | BindingFlags.Instance)
                   .GetValue(dbContext, null);

dbSet.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance)
     .Invoke(new object[] { someEntityTypedAsObject }); 

Or you can store the DbSet<TEntity> as a dynamically-typed reference. This way, you can call it without reflection. It's a performance and readability gain:

dynamic dbSet = dbContext
                       .GetType()
                       .GetProperty(tableName, BindingFlags.Public | BindingFlags.Instance)
                       .GetValue(dbContext, null);

dbSet.Add(someEntity);

2 Comments

I can't use DbSet<t> because I never know the entity, I ve juste the name of the table. I make an back office for change value of reference table, an generic interface..
@Yvan I've re-updated it. Check the dynamic part ;)
0

You shouldn't use GetProperty here, because context can contain entity sets, which were created using Set/Set<T> methods (thus, without any properties declared within context type).

The second, assuming, that entity types are unknown statically, you need to cast the result of non-generic Set call to non-generic DbSet type, and call its Add/Remove/etc methods.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.