-1

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可以正常工作。那么我在这里做错了什么?

4

1 回答 1

1

在竞争条件下Select MAX,可能会在您插入后立即返回由其他人生成的 ID。此外,identity不必永远增长——它可能会reseeded甚至转为负数。它还做了不适当的额外select工作。

SCOPE_IDENTITY是您(以及大多数其他人)案例的唯一正确方法。

此外,我建议将两个查询放在一个查询中,并用事务围绕两个插入。这样rollbackDriver如果Car.

于 2016-02-15T10:44:05.297 回答