C# ADO.NET插入Driver表时如何获取addressId等关联表外键ID值
外键ID获取与代码修复方案
一、外键ID的两种获取逻辑
根据业务场景分为两种情况处理:
- 关联数据(地址、车辆、油卡)已提前录入系统
这是最常见的场景:用户填写司机信息时,会在下拉选择器中选已经存在的地址、车辆、油卡,你只需要根据用户选择的关联数据唯一标识,提前查询对应表拿到主键ID即可,示例查询逻辑:
车辆ID、油卡ID的查询逻辑和上面完全一致,查询操作要放在Driver表插入之前,同一个事务内执行。// 示例:根据用户选择的地址编号查addressId string getAddressIdSql = "SELECT Id FROM Address WHERE AddressCode = @AddressCode"; using (SqlCommand cmd = new SqlCommand(getAddressIdSql, connection, transaction)) { cmd.Parameters.AddWithValue("@AddressCode", 用户选择的地址编号); object result = cmd.ExecuteScalar(); if (result == null) { // 校验不通过,回滚事务,提示用户选择的地址不存在 transaction.Rollback(); return; } addressId = (int)result; } - 关联数据和司机信息同时新增
如果地址、车辆、油卡是本次录入司机时一起新增的,你需要先执行关联表的插入操作,用SCOPE_IDENTITY()拿到新生成的主键ID,再给Driver表的外键参数赋值:
车辆、油卡的新增拿ID逻辑同上,同样要放在同一个事务内执行。// 示例:先插入新地址,拿addressId string insertAddressSql = "INSERT INTO Address (Street,City,PostCode) VALUES (@Street,@City,@PostCode);SELECT CAST(scope_identity() AS int)"; using (SqlCommand cmd = new SqlCommand(insertAddressSql, connection, transaction)) { cmd.Parameters.AddWithValue("@Street", driver.Address.Street); cmd.Parameters.AddWithValue("@City", driver.Address.City); cmd.Parameters.AddWithValue("@PostCode", driver.Address.PostCode); addressId = (int)cmd.ExecuteScalar(); }
二、现有代码的BUG修复
你贴的代码有几处明显错误会导致运行失败,需要修改:
- 驾照类型插入逻辑里参数赋值错误:你把licenseTypeId的key赋值给了
@driverid参数,正确写法是:int key = Alldriverlicensetypes.FirstOrDefault(x => x.Value == licensetype).Key; // 原错误写法:command.Parameters["@driverid"].Value = key; command.Parameters["@licenseID"].Value = key; - 驾照类型插入时重复开启连接、滥用事务:你开了新的
licenseconnection但又用已经关闭的旧connection开启事务,还重复打开连接,建议把驾照插入逻辑也放到最开始的同一个事务内,不要新开连接:// 前面Driver插入完成拿到newdriverID后,直接在同一个connection和事务里执行驾照插入 foreach (string licensetype in driver.DriversLicenceType) { if (Alldriverlicensetypes.ContainsValue(licensetype)) { string insertLicenseQuery = "INSERT INTO [DriverLicenseType] (driverId,licenseTypeId) Values (@driverid,@licenseID)"; using (SqlCommand cmd = new SqlCommand(insertLicenseQuery, connection, transaction)) { cmd.Parameters.AddWithValue("@driverid", newdriverID); int licenseId = Alldriverlicensetypes.First(x => x.Value == licensetype).Key; cmd.Parameters.AddWithValue("@licenseID", licenseId); cmd.ExecuteNonQuery(); } } else { // 自定义逻辑:比如新增未知驾照类型,或者抛出错误提示 transaction.Rollback(); throw new Exception($"不存在的驾照类型:{licensetype}"); } } // 所有操作都完成后再提交事务 transaction.Commit(); - 不要在catch里重新new Exception抛出,会丢失原始错误栈,直接throw即可:
catch (Exception ex) { transaction.Rollback(); // 原错误写法:throw new Exception(ex.Message); throw; }
内容的提问来源于stack exchange,提问作者Baggless
相关产品推荐
相关产品推荐

