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

C# ADO.NET插入Driver表时如何获取addressId等关联表外键ID值

外键ID获取与代码修复方案

一、外键ID的两种获取逻辑

根据业务场景分为两种情况处理:

  • 关联数据(地址、车辆、油卡)已提前录入系统
    这是最常见的场景:用户填写司机信息时,会在下拉选择器中选已经存在的地址、车辆、油卡,你只需要根据用户选择的关联数据唯一标识,提前查询对应表拿到主键ID即可,示例查询逻辑:
    // 示例:根据用户选择的地址编号查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;
    }
    
    车辆ID、油卡ID的查询逻辑和上面完全一致,查询操作要放在Driver表插入之前,同一个事务内执行。
  • 关联数据和司机信息同时新增
    如果地址、车辆、油卡是本次录入司机时一起新增的,你需要先执行关联表的插入操作,用SCOPE_IDENTITY()拿到新生成的主键ID,再给Driver表的外键参数赋值:
    // 示例:先插入新地址,拿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();
    }
    
    车辆、油卡的新增拿ID逻辑同上,同样要放在同一个事务内执行。

二、现有代码的BUG修复

你贴的代码有几处明显错误会导致运行失败,需要修改:

  1. 驾照类型插入逻辑里参数赋值错误:你把licenseTypeId的key赋值给了@driverid参数,正确写法是:
    int key = Alldriverlicensetypes.FirstOrDefault(x => x.Value == licensetype).Key;
    // 原错误写法:command.Parameters["@driverid"].Value = key;
    command.Parameters["@licenseID"].Value = key;
    
  2. 驾照类型插入时重复开启连接、滥用事务:你开了新的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();
    
  3. 不要在catch里重新new Exception抛出,会丢失原始错误栈,直接throw即可:
    catch (Exception ex) {
        transaction.Rollback();
        // 原错误写法:throw new Exception(ex.Message);
        throw;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:27:04