【问题标题】:EntityFrameworkCore reading data using reflection - how to create DbSet when type unknownEntityFrameworkCore 使用反射读取数据——类型未知时如何创建 DbSet
【发布时间】:2023-02-12 00:56:03
【问题描述】:

我正在使用 .Net 6 控制台应用程序,我需要从自定义的表中读取数据数据库上下文使用Microsoft.EntityFrameworkCore

我已将实体添加到模型中OnModelCreating()并可以通过调用来取回它们

var entity = ctx.Model.GetEntityTypes().FirstOrDefault(e => e.FullName().InfexOf(tableName) >= 0);

鉴于此,我如何检索数据列表,例如实体.ToList()- 为实体返回的类型是 IEntityType?。

作为替代方案(如果可能,也是我的首选方式),我使用反射创建了一个表数组(它们都继承自 BaseTable),它们存储为一个列表。

我想使用 DbContext.Set() 创建一个 DbSet<>,这样我就可以使用 Find()、AsNoTracking() 和其他此类命令(包括写操作)。

我有以下内容:-

 IQueryable<Object>dbSet = (IQueryable<Object>)ctx
                                                .GetType()
                                                .GetMethod("Set",1,Type.EmptyTypes)
                                                .MakeGenericMethod(t)   
                                                .Invoke(ctx, null);

这允许我执行类似 dbSet.ToList() 的操作,但我真的很想将其转换为 DbSet。

有谁知道是否可以进行这样的转换?

(我只从几组表中读取几条记录,然后将数据写回不同的数据库(具有相同的表)。

更新:*另一种思考方式:我正在遍历一组表。我需要取出 PK 和其他两列(我在运行时为其命名) - 如果第 1 列的值包含特定值,我需要更新第 2 列的值 *

【问题讨论】:

  • EF Core 就是关于加载/存储对象的。如果您实际上并不关心对象,您可能会发现使用原始 sql 工具会更容易。
  • 你有例子吗?我更新了我原来的帖子,在底部澄清了我想做什么
  • 如果这些表有一些共同点,那么这些类应该实现一个接口。然后您可以使用泛型从任何集合中加载和修改这些列。 Get&lt;T&gt;() where T:ICommon =&gt; db.Set&lt;T&gt;().Select(t =&gt; { t.Id, .... }); 然后用反射调用你的泛型方法。
  • 谢谢回复。这里的假设是我在编译时知道这些字段(t.Id,...),但我不知道这些字段是在运行时计算的。这就是我尝试使用 Linq.Expression 在 Select() 语句中构建 lambda 的原因。

标签: c# entity-framework-core .net-6.0


【解决方案1】:

你不能真的那样做。但是,您可以根据鉴别器将数据库值转换为特定类型。看看这个https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=data-annotations

【讨论】:

  • 谢谢,我真的需要能够根据表的反映(运行时)类型动态创建 DbSet。它似乎已被编码为仅使用静态类型。
  • 是的,EfCore 实体是硬编码的。拥有动态类型的唯一方法是将它们声明为对象,然后使用值转换器对对象进行序列化和反序列化(这是因为多态反序列化是不可能的)。但如果你能详细说明实际用例,我们可能会找到解决方案。具体来说,如果您有 XY 问题。
  • 谢谢,我已经在上面的评论中描述了这个问题,但为了简洁起见,我有一个 DbContext 引用了未知数量的表。我有一个列名列表,其内容在我检索值的另一个系统中充当查找表的键。检索到的值必须写回同一个表中的另一列。如果可以根据表的反射类型构造一个 DbSet,解决方案将是几行代码(我可以在运行时构造一个包含 PK 属性和两个字段的实体对象)。
  • 很难做到这一点。您可以在运行时发出 EfCore 类,但复杂性不值得。正如上面@Jeremy Lakeman 所提到的,EfCore 是关于存储域对象的。您最好使用原始 SQL。作为旁注,您可能真的想查看架构。
  • 谢谢,我查看了在使用 SQL SMO 时使用 SQL 查询,但是它们很快变得复杂,并且很难处理返回的数据。在架构方面,这是很常见的事情,在 OO-DB 中更是如此。在我看来,这是 EF 不支持反射的编码限制。我会考虑提出增强请求。
【解决方案2】:

我认为有办法。我只是将 ef core 与使用 emit 创建的动态对象一起使用。也许这个网站可以帮助你:EF Core with dynamic unknown types

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2013-09-15
    • 1970-01-01
    • 2018-12-27
    • 2019-10-12
    • 1970-01-01
    相关资源
    最近更新 更多