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
相关产品推荐
相关产品推荐

