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
获得的 PropertyInfo
的 PropertyType
找到该类型。获得一个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).
我想 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
获得的 PropertyInfo
的 PropertyType
找到该类型。获得一个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).