C# 和 SQL 初学者在这里。我有两个表使用 table1
的主键作为 table2
中的外键。为了获得 ID,我正在使用 SELECT MAX
并且一切都按照我想要的方式工作(下面的代码(:
{
con1.Open();
SqlCommand cmd1 = new SqlCommand();
cmd1.CommandText = "INSERT INTO dbo.testDriver(name) Values(@name)";
cmd1.Connection = con1;
cmd1.Parameters.AddWithValue("@name", name.Text);
cmd1.ExecuteNonQuery();
cmd1.Parameters.Clear();
cmd1.CommandText = "SELECT MAX(PkDriverID) FROM dbo.testDriver";
int FkDriverID = Convert.ToInt32(cmd1.ExecuteScalar());
cmd1.CommandText = "INSERT INTO dbo.testCar(brand, model, FkDriverID) Values(@brand, @model, @FkDriverID)";
cmd1.Connection = con1;
cmd1.Parameters.AddWithValue("@brand", brand.Text);
cmd1.Parameters.AddWithValue("@model", model.Text);
cmd1.Parameters.AddWithValue("@FkDriverID", FkDriverID);
cmd1.ExecuteNonQuery();
cmd1.Parameters.Clear();
con1.Close();
}
{
Response.Redirect(this.Request.Url.ToString());
}
但是同事们告诉我,我应该使用SCOPE_IDENTITY()
而不是SELECT MAX
。我确实明白为什么要使用它(在多个用户等的情况下(,但是用它替换SELECT MAX
后,我收到一个错误:
对象不能从 DBNull 强制转换为其他类型。
在我的数据库中,PK 和 FK 具有 int 数据类型,不允许使用 Null,并且SELECT MAX
它就可以工作了。那么我在这里做错了什么?
在竞争条件下Select MAX
可能会在您插入后立即返回其他人生成的 ID。此外,identity
不必永远增长——它可能reseeded
甚至变回负面。此外,它还会进行不适当的额外select
工作。
对于您(以及大多数其他人(的情况,SCOPE_IDENTITY
是唯一正确的方法。
此外,我建议将两个查询合并为一个查询,并用事务将两个插入项括起来。这样,您就可以rollback
更改Driver
如果Car
出现问题。