C#:SQL Server查询问题

问题描述:

我创建SQL Server Management Studio中的表使用此代码:C#:SQL Server查询问题

CREATE TABLE contact(
ID INT IDENTITY NOT NULL, 
FIRSTNAME VARCHAR(100), 
LASTNAME VARCHAR(100) 
) 

,并在C#中我用这个代码:

SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE"); 

SqlDataAdapter sd = new SqlDataAdapter(); 

sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(@ID, @FIRSTNAME, @LASTNAME)"); 

sd.InsertCommand.Parameters.Add("@ID", SqlDbType.Int).Value = textBox1.Text; 
sd.InsertCommand.Parameters.Add("@FIRSTNAME", SqlDbType.VarChar).Value = textBox2.Text; 
sd.InsertCommand.Parameters.Add("@LASTNAME", SqlDbType.VarChar).Value = textBox3.Text; 

sc.Open(); 

sd.InsertCommand.ExecuteNonQuery(); 

sc.Close(); 

,但是当我添加值到数据库中,我得到的错误:

"ExecuteNonQuery: Connection property has not been initialized"

,我加入sc给我的第一insertcommand固定它,但是当我运行程序我得到另一个错误:

An explicit value for the identity column in table 'contact' can only be specified when a column list is used and IDENTITY_INSERT is ON.

+4

您应该将连接创建封装在'using'语句中。 – Oded

+0

您没有将DataAdapter连接到连接 –

+0

为什么直接使用'DataAdapter'而不是'Command'? – Oded

这样来做:

using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE")) 
{ 

    using(SqlCommand command = new SqlCommand()) 
    { 
    command.CommandText = "INSERT INTO contact (FirstName, LastName) VALUES(@FIRSTNAME , @LASTNAME"); 
    command.CommandType = CommandType.Text; 
    command.Connection = sc; 

    command.Parameters.AddWithValue("@FIRSTNAME", textBox2.Text); 
    command.Parameters.AddWithValue("@LASTNAME", textBox3.Text); 

    sc.Open(); 

    command.ExecuteNonQuery(); 

    } 

} 

重要注意事项:

1)设置你的表最多有标识列作为一个标识列,并设置自动增量为真。当您插入时,这将自动生成数字ID

2)您试图插入标识列 - 除非启用标识插入,否则实际上无法执行此操作。我不会打扰 - 只需使用自动增量列并让数据库控制id生成步骤。

您可以生成你的表是这样的:

CREATE TABLE Contact 
(
Id int PRIMARY KEY IDENTITY, 
FirstName varchar(100), 
LastName varchar(100) 
) 

得到一个自动增量的主键。

3)你不需要SqlDataAdapter。

+1

我通常避免使用'SqlParameter.AddWithValue(..)'调用 - ADO.NET需要猜测传入的数据的类型,并在大多数情况下都正确 - 但它可能会出错。我喜欢**明确**定义类型,以便我没有讨厌的惊喜..... –

+0

嗨marc_s,我从来没有出错,但那是因为我通常只是懒惰,没有定义整个参数,但是传递正确的类型 - 我知道该列是一个int,该列是一个字符串等等等等。它还使得使用KeyValuePair style方法编写通用运行存储过程变得很容易。公平的评论,特别是当用户直接从用户输入驱动的字段调用存储过程:-) – dash

+0

...或者 - 如果 - 无论出于何种原因 - 传入的值是空值 - 哪种数据类型应该ADO。 NET *猜测*为? –

您需要将您要使用到的SqlCommand

InsertCommand = new SqlCommand("INSERT INTO contact VALUES(@ID , @FIRSTNAME , @LASTNAME)", sc); 

您需要配置您的连接和命令,以及连接。这样做的标准模式是:

using (SqlConnection conn = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE")){ 
    conn.Open(); 
    using (SqlCommand command = new SqlCommand(sqlString, conn)){ 
    //stuff... 
    command.ExecuteNonQuery(); 
    } 
} 
+0

噢是的,我不知道我是怎么忘记它的,非常感谢 –

+0

关注评论downvote?我看不出有什么问题吗? –

SqlConnectionSqlDataAdapter没有关系。其实你不需要SqlDataAdapter。您只需要SqlConnectionSqlCommand,您必须使用接受连接的构造函数重载。

你需要sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(@ID , @FIRSTNAME , @LASTNAME)", sc);

由于IDINT IDENTITY字段,因此您不应(也不能)向其中插入值。但是,如果使用“通用”INSERT语句而没有明确指定要插入值的列,则INSERT语句将尝试将数据插入所有列 - 包括ID,您无法插入任何内容。

解决方案(我推荐使用总是)是明确定义其列值插入:

INSERT INTO dbo.contact(FirstName, LastName) VALUES(@FIRSTNAME, @LASTNAME) 

,如果你需要改变你的表并添加另一列这也适用 - 你原来的陈述将失败,因为表格现在突然有四列,但你的陈述只会提供三个值。如果您明确定义了要为其提供值的列,那么您的语句更健壮并且效果更好。

所以你完整的代码应该是这样的:

using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE")) 
using(SqlCommand cmdInsert = new SqlCommand("INSERT INTO dbo.Contact(FirstName, LastName) VALUES(@FIRSTNAME, @LASTNAME)", sc)) 
{ 
    cmdInsert.Parameters.Add("@FIRSTNAME", SqlDbType.VarChar, 100).Value = textBox2.Text; 
    cmdInsert.Parameters.Add("@LASTNAME", SqlDbType.VarChar, 100).Value = textBox3.Text; 

    sc.Open(); 
    cmdInsert.ExecuteNonQuery(); 
    sc.Close(); 
} 

你可以做任何方式:

一个。设置你的连接对象适配器的连接的InsertCommand:

sd.InsertCommand.Connection = sc; 

或者

湾在初始化插入命令时传递连接对象,如下所示:

sd.InsertCommand = 
new SqlCommand("INSERT INTO contact VALUES(@ID, @FIRSTNAME, @LASTNAME)", sc);