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

C# Dapper多对多插入实现及现有代码问题修复咨询

解决方案

1. tags列表插入Person表处理

关系型数据库不支持直接存储列表类型,按需选择以下两种方案即可:

  • 轻量存储方案:将List<string>类型的tags序列化为逗号分隔字符串/JSON字符串,存入Person表的单个nvarchar类型字段,读取时再反序列化为列表即可,示例转换代码:string.Join(",", obj.C)
  • 可查询方案:如果后续需要按标签筛选Person数据,单独新建PersonTag表,字段包含ID、PersonID、Tag内容,插入Person记录后遍历tags列表批量插入该表即可。

2. 现有代码修复

修复点说明

  • 修正MyObject类的属性语法错误
  • 补充异步方法的await关键字,调整入口方法为异步支持
  • 插入SQL补充OUTPUT inserted.主键字段语句,获取插入后的自增ID
  • 新增事务控制,避免部分插入成功导致的数据不一致
  • 调整SQL表名与你提供的业务表(Person/Test/Staging)对齐
  • 补充参数绑定,修复原来未传参插入的问题

修复后完整代码

using Dapper;
using System.Data.SqlClient;
using System.Text.Json;

class Program
{
    // 调整入口为异步方法,支持await
    static async Task Main(string[] args)
    {
        var cs = @"Server=DESKTOP-FSNG2D1;Database=msdb;Trusted_Connection=True;";
        using var con = new SqlConnection(cs);
        con.Open();
        // 开启事务,保证数据一致性
        using var tran = con.BeginTransaction();

        try
        {
            MyObject obj = new MyObject();
            obj.A = "Leiz Gab"; // 对应JSON里的name字段
            obj.C = new List<string> { "tagA", "tagB", "tagC" }; // 对应tags列表

            Test tst = new Test();
            tst.Firstname = "A";
            tst.Surname = "Avd";
            Test tst1 = new Test();
            tst1.Firstname = "B";
            tst1.Surname = "Brgu";

            obj.D.Add(tst);
            obj.D.Add(tst1);

            // 插入Person主表,OUTPUT返回自增PersonID
            // 这里@C存储逗号分隔的tags,用方案1的话直接这么写即可
            string pINSERT = @"INSERT INTO [msdb].[dbo].[Person] (Name, Tags) 
                               OUTPUT inserted.ID
                               VALUES(@Name, @Tags)";
            // 绑定参数,tags转逗号分隔字符串
            var personParams = new 
            {
                Name = obj.A,
                Tags = string.Join(",", obj.C)
            };
            int personId = await con.ExecuteScalarAsync<int>(pINSERT, personParams, tran);

            // 插入Test子表+关联表
            string tINSERT = @"INSERT INTO [msdb].[dbo].[Test] (Surname, Firstname) 
                               OUTPUT inserted.ID
                               VALUES(@Surname, @Firstname)";
            string aINSERT = @"INSERT INTO [msdb].[dbo].[Staging] (PersonID, TestID) 
                               VALUES(@PersonID, @TestID)";

            foreach (var testItem in obj.D)
            {
                // 插入Test获取自增TestID
                int testId = await con.ExecuteScalarAsync<int>(tINSERT, testItem, tran);
                // 插入关联表
                await con.ExecuteAsync(aINSERT, new { PersonID = personId, TestID = testId }, tran);
            }

            // 所有操作成功提交事务
            tran.Commit();
        }
        catch
        {
            // 出错回滚
            tran.Rollback();
            throw;
        }
    }
}

public class MyObject
{
    public string A { get; set; }
    public string B { get; set; }
    // 对应tags列表
    public List<string> C { get; set; } = new List<string>();
    // 修正属性语法错误
    public List<Test> D { get; set; } = new List<Test>();
}

public class Test
{
    public int ID { get; set; }
    public string Surname { get; set; }
    public string Firstname { get; set; }
}

public class Staging
{
    public int ID { get; set; }
    public int PersonID { get; set; }
    public int TestID { get; set; }
}

额外说明

如果你的Person表字段和示例不一致,调整pINSERT语句的字段名和参数对应关系即可。如果需要用tags单独存表的方案,只需要在插入Person成功后,新增遍历obj.C插入PersonTag表的逻辑即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:24:04