.NET循环调用存储过程报错:已添加相同键StudentId
问题解决:An item with the same key has already been added. Key: StudentId
错误原因
LinkStudentToSubjectsAsync方法中,parameters字典在foreach循环外部初始化,每次循环都会向同一个字典添加StudentId和SubjectId键。第一次循环执行后,这两个键已存在于字典中,第二次循环执行parameters.Add时就会触发重复键异常。
修复方案
1. 调整参数字典初始化位置
将parameters字典的创建移至foreach循环内部,确保每次循环都使用全新的字典,避免重复添加键:
public async Task<bool> LinkStudentToSubjectsAsync(int studentId, int[] subjectIds) { DeleteSubjectStudentLinks(studentId); StudentSubject? linkResult = null; foreach (var subjectId in subjectIds) { // 每次循环新建参数字典 var parameters = new Dictionary<string, object>(); parameters.Add(StoredProcedures.Params.StudentId, studentId); parameters.Add(StoredProcedures.Params.SubjectId, subjectId); linkResult = await _repository.ExecuteStoredProcAsync<StudentSubject>(StoredProcedures.LinkStudentSubjects, parameters); } return linkResult is not null; }
2. 清理存储过程多余参数
存储过程中的@StudentSubjectID参数未被使用,且调用时未传入该参数,会导致调用异常,需删除该参数:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[LinkStudentSubjects] @StudentID int, @SubjectID int AS BEGIN DECLARE @TableStudentSubjectID TABLE (ID int) -- 恢复并修正重复判断逻辑,避免重复插入关联记录 IF NOT EXISTS (SELECT 1 FROM [dbo].[StudentSubjects] WHERE StudentID = @StudentID AND SubjectID = @SubjectID) BEGIN INSERT INTO [dbo].[StudentSubjects] (StudentId, SubjectId) OUTPUT inserted.id INTO @TableStudentSubjectID(ID) VALUES (@StudentID, @SubjectID) END SELECT ID FROM @TableStudentSubjectID END
3. 额外优化建议
- 如果
DeleteSubjectStudentLinks是数据库操作,建议改为异步方法DeleteSubjectStudentLinksAsync并使用await调用,避免阻塞线程。 - 可以考虑批量插入代替循环调用存储过程(比如将
subjectIds作为表值参数传入存储过程),提升执行性能。
内容的提问来源于stack exchange,提问作者Zidane
相关产品推荐
相关产品推荐

