add/update 数据库中的数据如何使用反射

How add/update data in db with reflection

我想 save/update 我在数据库中的更改与反射。 我只有 table 的名称和字段的 ID pk。 我尝试用反射更新这个 table...

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

首先我有 table 和 Iqueryable 我不知道如何在数据库中更新我的 table。

有什么帮助吗?

感谢

你不需要 DbSet<TEntity> 吗?

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

Now call DbSet<TEntity> methods 就像您在常规情况下所做的那样,因为您输入了 DbSet<T>.

可查询对象对您帮助不大,因为正如您已经猜到的那样,它是关于查询而不是执行写回数据库的操作。

OP 说...

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..

然后,您的解决方案甚至会通过反射将实体添加到 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 }); 

或者您可以将 DbSet<TEntity> 存储为动态类型引用。这样,你就可以不经反射地调用它。这是性能和可读性的提升:

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

dbSet.Add(someEntity);

你不应该在这里使用 GetProperty,因为上下文可以包含实体集,这些实体集是使用 Set/Set<T> 方法创建的(因此,没有在上下文类型中声明任何属性)。

第二,假设实体类型是静态未知的,您需要将非泛型 Set 调用的结果转换为非泛型 DbSet 类型,并调用其 Add/Remove/等方法。

这个答案是为了您应该做的事情的完整性。使用 Set (非通用版本)是正确的方法。我知道你只知道tableName(连你实体的Type都不知道)。但是 Set 需要一个 Type。因此,您需要根据从 tableName 获得的 PropertyInfoPropertyType 找到该类型。获得一个DbSet(非泛型)后,你可以使用它的所有方法,无需再进行任何反射。传入的实体将只是 object。详细代码如下:

//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).