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

运行时如何选择正确的DBSet进行查询?(EF6场景)

解决方案:基于EF6的多类型车辆查询(符合开闭原则)

以下是几种无需if-else、遵循开闭原则的实现方案,可根据项目场景选择:

方案一:泛型方法+反射调用

封装通用泛型查询逻辑,通过反射根据传入对象的实际类型动态调用对应版本:

public class TestClass {
    SqlTestContext context = new SqlTestContext("connection string");

    public Vehicle returnExistingFromDatabase(Vehicle vehicleObject) {
        var entityType = vehicleObject.GetType();
        // 获取泛型查询方法并动态指定类型参数
        var queryMethod = typeof(TestClass).GetMethod(nameof(GetExistingEntity), BindingFlags.NonPublic | BindingFlags.Instance)
                                           .MakeGenericMethod(entityType);
        return (Vehicle)queryMethod.Invoke(this, new object[] { vehicleObject.Id });
    }

    // 通用泛型查询方法,约束为实现Vehicle的实体类
    private T GetExistingEntity<T>(string id) where T : class, Vehicle {
        return context.Set<T>().SingleOrDefault(e => e.Id == id);
    }
}

说明:新增Vehicle实现类时,只需在DbContext中注册对应DBSet,无需修改TestClass的代码,完全符合开闭原则。

方案二:策略模式(类型映射+委托)

预先注册每种车辆类型的查询逻辑,后续扩展仅需添加映射项:

public class TestClass {
    SqlTestContext context = new SqlTestContext("connection string");
    // 存储类型与查询委托的映射关系
    private readonly Dictionary<Type, Func<string, Vehicle>> _queryStrategies;

    public TestClass() {
        _queryStrategies = new Dictionary<Type, Func<string, Vehicle>> {
            { typeof(Car), id => context.Car.SingleOrDefault(c => c.Id == id) },
            { typeof(Bicycle), id => context.Bicycle.SingleOrDefault(b => b.Id == id) }
        };
    }

    public Vehicle returnExistingFromDatabase(Vehicle vehicleObject) {
        if (_queryStrategies.TryGetValue(vehicleObject.GetType(), out var queryFunc)) {
            return queryFunc(vehicleObject.Id);
        }
        throw new ArgumentException($"未支持的车辆类型:{vehicleObject.GetType().Name}");
    }
}

说明:这种方式性能优于反射,逻辑直观。新增类型时仅需在构造函数的字典中添加新键值对,核心查询逻辑无需改动。

方案三:非泛型DbSet查询

直接利用EF的非泛型Set方法,结合类型转换实现查询:

public class TestClass {
    SqlTestContext context = new SqlTestContext("connection string");

    public Vehicle returnExistingFromDatabase(Vehicle vehicleObject) {
        var entityType = vehicleObject.GetType();
        var dbSet = context.Set(entityType);
        // 将非泛型DbSet转换为Vehicle可枚举集合后查询
        return dbSet.Cast<Vehicle>().SingleOrDefault(e => e.Id == vehicleObject.Id);
    }
}

说明:无需泛型或反射,但需确保所有Vehicle实现类的Id属性已正确映射到数据库列。

注意事项

  • 所有Vehicle实现类必须在SqlTestContext中注册对应的DBSet(如public DbSet<Car> Car { get; set; })。
  • 确保Vehicle接口的Id属性在实体类中通过DataAnnotations或Fluent API正确映射到数据库的id列。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:17:38