You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET中基于枚举动态查询EF Core不同DbSet类型?

问题描述

我拥有11张对应实体类均继承自BasePart的数据库表,希望使用同一前端代码完成所有表的展示、查询与编辑操作,但在EF Core 7中实现起来存在困难。

模型类定义如下:

public interface IPart
{
    [Key]
    int PartId { get; set; }
    string PartValue { get; set; }
    string Description { get; set; }
    string Symbol { get; set; }
    string Footprint { get; set; }
    string Price { get; set; }
    // Rest of the properties ...
}

public abstract class BasePart : IPart
{
    [Key]
    public int PartId { get; set; }
    public string PartValue { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string Symbol { get; set; } = string.Empty;
    public string Footprint { get; set; } = string.Empty;
    public string Price { get; set; } = string.Empty;
    // Rest of the properties ...
}

public class Resistor : BasePart
{
}

public class Capacitor : BasePart
{
}

public class Inductor : BasePart
{
}

// Rest of the derived models

public enum PartType
{
    Capacitor,
    Connector,
    Diode,
    Fuse,
    Inductor,
    IntegratedCircuit,
    Mechanical,
    Oscillator,
    Other,
    Resistor,
    Switch
}

期望实现的功能:通过下拉框选择PartType枚举值,将匹配的DbSet(如DbSet<Capacitor>)中的数据加载到IPart列表,用于数据网格展示。要求操作对所有模型通用,复用同一数据网格及加载、编辑、保存逻辑,避免重复编写11次相同代码。

但DbSet受类型安全限制,似乎不支持这种操作方式,理想实现代码如下:

void OnValueChanged(PartType? value)
{
    selectedDatabase = value;

    if (selectedDatabase.HasValue)
    {
        var partList = dbContext.Set(MapEnumToType(selectedDatabase.value)).ToList();
    }
}

请问是否存在合适的实现方案,还是必须实现仓储模式并为11个模型手写所有处理代码?

实现方案

不需要为每个模型手写重复代码,通过枚举-实体类型映射+EF Core动态DbSet操作就能实现通用逻辑,具体步骤如下:

1. 实现枚举到实体类型的映射

创建静态字典存储映射关系,避免硬编码,后续扩展只需补充字典项:

private static readonly Dictionary<PartType, Type> _partTypeEntityMap = new()
{
    { PartType.Capacitor, typeof(Capacitor) },
    { PartType.Resistor, typeof(Resistor) },
    { PartType.Inductor, typeof(Inductor) },
    { PartType.Connector, typeof(Connector) },
    // 补充剩余9个枚举项对应的实体类型
};

private Type MapPartTypeToEntity(PartType partType)
{
    return _partTypeEntityMap[partType];
}

2. 动态加载对应DbSet数据

利用EF Core的DbContext.Set(Type)方法获取动态DbSet,再转换为IPart类型列表适配前端:

void OnValueChanged(PartType? value)
{
    selectedDatabase = value;

    if (selectedDatabase.HasValue)
    {
        Type entityType = MapPartTypeToEntity(selectedDatabase.Value);
        // 动态获取DbSet并转为IPart列表
        var partList = dbContext.Set(entityType)
                                .Cast<IPart>()
                                .ToList();
        // 将列表绑定到前端数据网格数据源
        PartsGridDataSource = partList;
    }
}

3. 通用编辑与保存逻辑

针对IPart类型实现通用增改逻辑,通过类型判断获取对应DbSet完成操作:

async Task SavePart(IPart part)
{
    Type entityType = part.GetType();
    var dbSet = dbContext.Set(entityType);

    if (part.PartId == 0)
    {
        // 新增操作
        dbSet.Add(part);
    }
    else
    {
        // 更新操作:附加实体并标记为修改
        dbContext.Attach(part).State = EntityState.Modified;
    }

    await dbContext.SaveChangesAsync();
}

4. 表结构配置:确保EF Core识别独立表

因为使用11张独立表,需要在DbContext的OnModelCreating中配置**表每类型(TPT)**映射:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Resistor>().ToTable("Resistors");
    modelBuilder.Entity<Capacitor>().ToTable("Capacitors");
    modelBuilder.Entity<Inductor>().ToTable("Inductors");
    // 为剩余8个派生类添加类似表映射配置
}
说明

这种方案无需手写11次仓储实现,通过动态类型处理即可复用所有核心逻辑。后续扩展新的PartType,只需补充映射字典和表配置即可,维护成本极低。

内容的提问来源于stack exchange,提问作者Patrick Walther

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:24:57