2016-06-07 136 views
0

我試圖插入一個新的人的數據,我可以在第一次嘗試,但是當第二次嘗試和第二次嘗試給出錯誤違反主鍵,事實上,人ID(PERSONID)是它試圖添加一個新的人,每次遞增,所以我才意識到錯誤是主鍵違反PRIMARY KEY約束。不能在對象中插入重複的鍵 - ADO.NET

表人

CREATE TABLE [dbo].[Person] (
    [personID] INT NOT NULL, 
    [personName] VARCHAR (50) NOT NULL, 
    PRIMARY KEY CLUSTERED ([personID] ASC) 
); 

方法來創建並插入新的人

protected void BtnCreate(object sender, EventArgs e) 
    { 
     SqlConnection connection = new SqlConnection(connectionString); 
     //id to new person 
     int id = 0; 
     //command 
     string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)"; 

     SqlCommand cmd = new SqlCommand(command, connection); 
     cmd.Parameters.AddWithValue("@id", id++);//id increase 
     cmd.Parameters.AddWithValue("@name", name.Text); 
     connection.Open(); 
     cmd.ExecuteNonQuery(); 
     connection.Close(); 
    } 

a建議嗎?

+2

轉到您的數據庫模式並更改添加IDENTITY屬性的personID列。然後刪除任何嘗試爲自己設置personID – Steve

回答

1

如果你不與你的personID場的實際值,有關(其中你的代碼似乎表明)。而且,只是希望它是獨一無二的,並且增加1。

在什麼@Steve表明插圖,你可以定義你的表的方式:(在T-SQL)

CREATE TABLE [dbo].[Person] (
[personID] [int] IDENTITY(1,1) NOT NULL, 
[personName] VARCHAR (50) NOT NULL, 
    PRIMARY KEY CLUSTERED ([personID] ASC) 
); 

這將消除,然後你需要插入PERSONID

protected void BtnCreate(object sender, EventArgs e) 
    { 
     SqlConnection connection = new SqlConnection(connectionString); 

     //command 
     string command = "INSERT INTO [Person] ([personName]) VALUES (@name)"; 

     SqlCommand cmd = new SqlCommand(command, connection); 
     cmd.Parameters.AddWithValue("@name", name.Text); 
     connection.Open(); 
     cmd.ExecuteNonQuery(); 
     connection.Close(); 
    } 
4

您當前的代碼不能再次運行,因爲您增量的id變量是在堆棧上分配的局部變量。當方法退出時,堆棧中的所有內容都將被清除。再次單擊重新輸入方法的按鈕,但變量重置爲零,並且您的增量將變量再次設置爲1.因此,personID字段的重複例外。

我建議更改您的personID列添加IDENTITY屬性。
通過這種方式,數據庫計算自己下一個要分配給personID字段的值,並且不需要記住分配給表的最後一個id是什麼(這在多用戶中實際上不可能以安全的方式實現環境)

添加IDENTITY屬性後,你可以通過數據庫分配給您personID場改變你的查詢值進行讀回

string command = @"INSERT INTO [Person] ([personName]) 
        OUTPUT INSERTED.personID 
        VALUES (@name)"; 

和運行使用的ExecuteScalar

int id = Convert.ToInt32(cmd.ExecuteScalar()); 
查詢
0

史蒂夫有一個很好的答案,或者,如果不能重新安排你的DB模式,那麼你可以這樣做:

protected void BtnCreate(object sender, EventArgs e) 
{ 
    SqlConnection connection = new SqlConnection(connectionString); 

    connection.Open(); 

    SqlCommand idcommand = new SqlCommand("select max([personID]) from Person", connection) 
    //id to new person 
    int id = ((int)idcommand.ExecuteScalar()) + 1; 
    //command 
    string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)"; 

    SqlCommand cmd = new SqlCommand(command, connection); 
    cmd.Parameters.AddWithValue("@id", id++);//id increase 
    cmd.Parameters.AddWithValue("@name", name.Text); 
    cmd.ExecuteNonQuery(); 
    connection.Close(); 
} 
+3

的值我不會推薦這個。 MAX的問題是當你有多個用戶插入記錄時。遲早你會得到一個錯誤,因爲MAX可能會將相同的值返回給多個用戶。另一個(次要的)問題是這樣一個事實,即您將兩次訪問數據庫,這可能會影響性能。 – Steve

+1

我也不會推薦它,這是發佈爲*替代* - 有一些傳統的情況下,你不能不能改變數據庫架構。 –

1

謝謝大家,所有的答案都是正確的,但我發現了一個更好的解決方案,我用id作爲一個靜態值,初始化至少一個,並放棄了功能,它沒有任何錯誤地工作,並按我的意願工作,我感謝您的時間和可用性

我的表鴕鳥政策需要,因爲我打算進入ID增量每次按鈕按下時創建

CREATE TABLE [dbo].[Person] (
    [personID] INT NOT NULL, 
    [personName] VARCHAR (50) NOT NULL, 
    PRIMARY KEY CLUSTERED ([personID] ASC) 
); 

我用static int id = -1,出來的功能和it's工作新的人使用的身份細

//id to new person 
private static int id = -1; 

protected void BtnCreate(object sender, EventArgs e) 
    { 
     SqlConnection connection = new SqlConnection(connectionString); 

     //command 
     string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)"; 

     SqlCommand cmd = new SqlCommand(command, connection); 
     cmd.Parameters.AddWithValue("@id", id++);//id increase 
     cmd.Parameters.AddWithValue("@name", name.Text); 
     connection.Open(); 
     cmd.ExecuteNonQuery(); 
     connection.Close(); 
    } 
相關問題