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

C#将两张结构相同异名表的数据合并存入同一对象的优雅方案

可行的C#端实现方案

以下是两种常用的优雅实现方式,均不需要在SQL侧拼接UNION:


方案1:轻量ORM实现(推荐,以Dapper为例)

这种方式代码量最少,维护成本最低,只需要提前把字段列表统一抽出来,分别查询两张表后合并结果集即可:

// 统一抽离查询字段,避免重复编写、减少字段不匹配的BUG
var selectFields = "ID, mercid, mercname, termid, PAN, edcbatch, transeq, tranauth, trandt, trantm, trandbcr, tranamt";
var formalTable = applicationSettings.TablePOSSettlementRecords;
var investigateTable = applicationSettings.TablePOSSettlementRecords_investigations;

List<RegionalReportRecord> result = new List<RegionalReportRecord>();
using (var conn = new SqlConnection("你的数据库连接字符串"))
{
    // 分别查询两张表,自动映射到实体类
    var formalData = conn.Query<RegionalReportRecord>($"SELECT {selectFields} FROM {formalTable}").ToList();
    var investigateData = conn.Query<RegionalReportRecord>($"SELECT {selectFields} FROM {investigateTable}").ToList();

    // 合并结果:等效UNION ALL(不去重,性能更高)
    result.AddRange(formalData);
    result.AddRange(investigateData);

    // 如果需要和原SQL UNION逻辑一致(自动去重),替换成以下代码即可,前提是实体类已经重写Equals和GetHashCode方法
    // result = formalData.Union(investigateData).ToList();
}

方案2:原生ADO.NET实现(无需引入第三方ORM)

如果项目不能引入Dapper等外部依赖,可以自己封装统一的映射方法实现:

  1. 先编写通用的DataReader转实体类的映射方法:
private RegionalReportRecord MapToEntity(IDataReader reader)
{
    return new RegionalReportRecord
    {
        ID = reader.GetInt32(reader.GetOrdinal("ID")),
        MercId = reader.IsDBNull("mercid") ? null : reader.GetString(reader.GetOrdinal("mercid")),
        MercName = reader.IsDBNull("mercname") ? null : reader.GetString(reader.GetOrdinal("mercname")),
        TermId = reader.IsDBNull("termid") ? null : reader.GetString(reader.GetOrdinal("termid")),
        PAN = reader.IsDBNull("PAN") ? null : reader.GetString(reader.GetOrdinal("PAN")),
        EdcBatch = reader.IsDBNull("edcbatch") ? null : reader.GetString(reader.GetOrdinal("edcbatch")),
        TranSeq = reader.IsDBNull("transeq") ? null : reader.GetString(reader.GetOrdinal("transeq")),
        TranAuth = reader.IsDBNull("tranauth") ? null : reader.GetString(reader.GetOrdinal("tranauth")),
        TranDt = reader.IsDBNull("trandt") ? DateTime.MinValue : reader.GetDateTime(reader.GetOrdinal("trandt")),
        TranTm = reader.IsDBNull("trantm") ? null : reader.GetString(reader.GetOrdinal("trantm")),
        TranDbCr = reader.IsDBNull("trandbcr") ? null : reader.GetString(reader.GetOrdinal("trandbcr")),
        TranAmt = reader.IsDBNull("tranamt") ? 0 : reader.GetDecimal(reader.GetOrdinal("tranamt"))
    };
}
  1. 分别查询两张表合并结果:
var selectFields = "ID, mercid, mercname, termid, PAN, edcbatch, transeq, tranauth, trandt, trantm, trandbcr, tranamt";
var formalTable = applicationSettings.TablePOSSettlementRecords;
var investigateTable = applicationSettings.TablePOSSettlementRecords_investigations;
List<RegionalReportRecord> result = new List<RegionalReportRecord>();

using (var conn = new SqlConnection("你的数据库连接字符串"))
{
    conn.Open();
    // 查询正式表
    using (var cmd = new SqlCommand($"SELECT {selectFields} FROM {formalTable}", conn))
    using (var reader = cmd.ExecuteReader())
    {
        while(reader.Read()) result.Add(MapToEntity(reader));
    }
    // 查询核查表
    using (var cmd = new SqlCommand($"SELECT {selectFields} FROM {investigateTable}", conn))
    using (var reader = cmd.ExecuteReader())
    {
        while(reader.Read()) result.Add(MapToEntity(reader));
    }
}

注意事项

  • 你原来的SQL存在语法错误:第一张表查询返回12个字段,第二张表只返回10个字段,直接执行UNION会触发数据库字段数量不匹配的报错,以上两种方案统一了字段列表,可以避免该问题
  • 如果你的业务数据量超过10万条,更推荐使用SQL侧UNION方案,数据库的合并运算性能远高于C#端内存合并,同时减少两次查询带来的IO开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 11:06:03