【问题标题】:C# : SQL Server query issueC#:SQL Server 查询问题
【发布时间】:2011-12-03 20:39:35
【问题描述】:

我使用以下代码在 SQL Server Management Studio 中创建了一个表:

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:连接属性尚未初始化”

我通过将sc 添加到我的第一个insertcommand 来修复它,但是当我运行该程序时,我又遇到了另一个错误:

表 'contact' 中标识列的显式值只能 在使用列列表并且 IDENTITY_INSERT 为 ON 时指定。

【问题讨论】:

  • 您应该将连接创建包装在 using 语句中。
  • 您没有将 DataAdapter 连接到连接
  • 你为什么直接使用DataAdapter而不是Command
  • 我遇到了另一个问题:只有在使用列列表并且 IDENTITY_INSERT 为 ON 时,才能为表 'contact' 中的标识列指定显式值。
  • 如果您想得到答案,请将您的新问题放在一个新问题中。

标签: c# sql sql-server


【解决方案1】:

这样做:

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 列作为标识列,并将自动增量设置为 true。这将在您插入时自动生成一个数字 id

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

您可以通过这种方式生成表格:

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

获取自动递增的主键。

3) 您不需要 SqlDataAdapter。

【讨论】:

  • 我通常避免SqlParameter.AddWithValue(..) 调用——ADO.NET 需要猜测传入的数据类型,并且大部分时间都正确——但它可能会出错。我更喜欢显式地定义类型,这样我就没有讨厌的惊喜.....
  • 嗨,marc_s,我从来没有出错过,但那是因为我通常很懒惰,没有定义整个参数,但传递了正确的类型 - 我知道该列是一个int,该列是一个字符串,依此类推。它还使使用 KeyValuePair 样式方法编写通用运行存储过程变得容易。公平的评论,特别是当用户直接从用户输入驱动的字段调用存储过程时:-)
  • ... 或者如果 - 无论出于何种原因 - 传入的值是 null - ADO.NET guess 应该使用什么数据类型???
  • 我总是对此进行解析并提供 DBNull.Value,但是,点 :-)
  • 感谢 marc_s - 我目前正在使用 MySql 做一些事情,并将我的创建语句弄混了。我已经编辑了答案以反映这一点。
【解决方案2】:

您需要将您打算使用的连接传递给 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();
  }
}

【讨论】:

  • 哦,是的,我不知道我怎么忘记了,非常感谢
  • 想评论否决票?我看不出答案有什么问题?
【解决方案3】:

SqlConnectionSqlDataAdapter 之间没有关系。

事实上,你不需要SqlDataAdapter。您只需要SqlConnectionSqlCommand,您必须使用同样接受连接的构造函数重载。

【讨论】:

    【解决方案4】:

    由于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();
    }
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        你可以做任何一种方式:

        一个。将您的连接对象设置为适配器的插入命令连接:

        sd.InsertCommand.Connection = sc; 
        

        或者

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 1970-01-01
          • 2023-01-18
          相关资源
          最近更新 更多