Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将表值参数传递到Merge语句中,在空表上获取重复键错误?_C#_Sql Server_Stored Procedures_Table Valued Parameters - Fatal编程技术网

C# 如何将表值参数传递到Merge语句中,在空表上获取重复键错误?

C# 如何将表值参数传递到Merge语句中,在空表上获取重复键错误?,c#,sql-server,stored-procedures,table-valued-parameters,C#,Sql Server,Stored Procedures,Table Valued Parameters,我正在从C代码向MS SQL Server 2008 R2存储过程发送一个表值参数。我收到的错误是: 违反主键约束“PK_Example.ExampleTable”。无法在对象“Example.ExampleTable”中插入重复键。 声明已终止 表结构: 例 [ID] (PK, int, not null) [Month] (PK, int, not null) [Year] (PK, int, not null) [ExternalTextReference] (varchar(150),

我正在从C代码向MS SQL Server 2008 R2存储过程发送一个表值参数。我收到的错误是: 违反主键约束“PK_Example.ExampleTable”。无法在对象“Example.ExampleTable”中插入重复键。 声明已终止

表结构: 例

[ID] (PK, int, not null)
[Month] (PK, int, not null)
[Year] (PK, int, not null)
[ExternalTextReference] (varchar(150), null)
[UserNote] (varchar(MAX), null)
[CheckedComplete] (bit, not null)
PK是唯一的约束。 存储过程:

ALTER PROCEDURE [dbo].[ExampleSaveGridCheckBatch]
@IDs IDLIST readonly,
@year int = 0,
@month int = 0,
@checked bit = 0
AS
BEGIN
     SET NOCOUNT ON;
     MERGE INTO [Example].[ExampleTable] AS Target 
     USING ( select * from @IDs )
            AS Source (ID)
     ON Target.ID = Source.ID
     WHEN MATCHED THEN
          UPDATE SET CheckedComplete = @checked
     WHEN NOT MATCHED BY TARGET THEN
          INSERT ([ID], [Year], [Month], [CheckedComplete]) 
          VALUES (Source.ID, @year, @month, @checked);
END
对于上面的IDLIST部分:创建类型IDLIST作为表n int

C代码:

DataTable table = new DataTable("IDsList");            
DataColumn col1 = new DataColumn("ID", System.Type.GetType("System.Int32"));
table.Columns.Add(col1);

var cn = new SqlConnection();
createConnection(cn);

SqlCommand cmd = new SqlCommand("ExampleSaveGridCheckBatch", cn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@year", year);
cmd.Parameters.AddWithValue("@month", month);
cmd.Parameters.AddWithValue("@checked", checkstatus);
SqlParameter sparam = new SqlParameter("@IDs", SqlDbType.Structured);
foreach (int item in iDsList)
{
    table.Rows.Add(item);
}
sparam.Value = table;
cmd.Parameters.Add(sparam);

cmd.ExecuteNonQuery();
执行时,我会得到错误。在示例集中,变量如下所示: 年份:2011年 月份:11 检查状态:1 iDsList:71个唯一整数的列表

我的函数的目的是有人在网格上单击check all,我将选中的状态保存到数据库中每个受影响的行,而不必逐一检查。这是一个通过规范化创建的辅助表,因此每个表可能有记录,也可能没有记录,因此合并。我得到了错误,并决定通过截断表并重试来简化问题,但即使是一个绝对空的表,我也会得到重复键错误

因此,核心问题是如何在没有记录的情况下出现重复键错误,以及如何修复该错误以不再出现错误?

在示例表中,月份和年份列也与ID一起标记为主键,我猜它们不包含唯一值。
请删除表中月份和年份列的主键约束,然后重试。

是否确实71个整数的列表实际上是唯一的?是否尝试使用较小的列表?。如果您更改sp并将其设置为:`使用@IDs中的select DISTINCT ID作为源ID`,会发生什么情况?我敢肯定。71是从另一个强制唯一约束的表中提取出来的,我可以直观地验证它们是否唯一。Distinct修复了它并揭示了问题。我还不知道为什么,但它在每条记录中添加了一个0 ID双精度。仍然不确定为什么会出现没有记录行的重复错误。这确实解决了问题的实际问题部分,为什么会出现错误?部分是学术性的,尽管我想知道。这意味着您从@ids查询SELECT Id检索的Id列表不是唯一的。因此,即使您的表是空的,您仍然试图插入重复的记录。因为您的查询失败了,所以它回滚并且实际上没有插入任何行。实际上,问题和问题是由Lamak在上面的评论中回答的,而不是在答案中。这有点回避了问题,可能会导致重复,尽管这会暴露出问题,我们使用的一个编码错误的DevExpress产品正在注入神奇的零ID行。我不会用任何方式来标记拉马克的评论作为答案,我会标记这个。