【问题标题】:Invalid Cast when dealing with @@Identity处理 @@Identity 时的无效演员表
【发布时间】:2012-07-27 14:18:22
【问题描述】:

我有一个包含以下类方法的 winforms 应用程序:

public aSqlQuery(SqlCommand pSqlCom, string pMode = "object", bool pGetID = false)
    {
        try
        {
            string strConnection = aSystem.ConnectionString;
            SqlConnection linkToDB = new SqlConnection(strConnection);
            pSqlCom.Connection = linkToDB;

            switch (pMode)
            {
                case "non query":
                    {
                        linkToDB.Open();
                        pSqlCom.ExecuteNonQuery();
                        if (pGetID == true)
                        {
                            SqlCommand sqlCom = new SqlCommand("SELECT @@IDENTITY;", linkToDB);
                            this.LastID = (int)sqlCom.ExecuteScalar();
                        }
                        linkToDB.Close();
                    }
                    break;

加上其他开关

pSqlCom (SqlCommand) 执行得很好,因为我可以看到写入数据库的数据。然而,随后的“SELECT @@IDENTITY”语句给出了一个无效的转换错误 我做错了什么,如何在我的类方法中检索 SQL 创建的新 ID?

【问题讨论】:

  • 什么是“sqlCom.ExecuteScalar();”真的回到你身边了吗?
  • 这是一个很好的资源,请阅读完整的主题,与@Martin Smith stackoverflow.com/questions/1174930/…相同
  • @Yaroslav - 不知道你为什么要告诉我读它。那里的答案绝不会否定我对您的答案所做的评论。
  • 我可能在问一个愚蠢的问题,但是您确定执行 INSERT 的表包含 IDENTITY 列吗?我有像你这样的代码,从来没有见过这个问题。
  • @Steve 这可以解释为什么 @@IDENTITY 返回 null 并且强制转换失败。

标签: c# sql winforms


【解决方案1】:

插入行并获取使用SCOPE_IDENTIY() 给出的ID,不要使用@@IDENTITY

您需要在相同的连接和范围上使用SCOPE_IDENTITY(),就在INSERT之后。


在您的示例中,没有在您的连接上执行 INSERT,因此您不能期望获得最后生成的 Id。

在您的示例中,不清楚pSqlCom 执行INSERT,如果不执行任何标识函数将返回无法转换为intNULL


编辑

您想使用SCOPE_IDENTITY(),并且想在与INSERT 相同的Command 中执行此操作。

所以,你的陈述应该是这样的

var sql =
@"INSERT <Your Data> <Your Table>;
SELECT SCOPE_IDENTIY();"

using (SqlConnection connection = new SqlConnection(strConnection))
{
    using (SqlCommand command = new SqlCommand(sql, connection))
    {
        connection.Open();
        object result = command.ExecuteScalar();
    }
}

int? id = (int?)(!Convert.IsDBNull(result) ? result : null);

【讨论】:

  • Scope_Identity() 给出了同样的错误信息。请明确范围。我认为如果 pSqlCom AND "SELECT SCOPE_IDENTIY();"在同一连接上背靠背执行的情况下,这将被称为“相同范围”。我的假设错了吗?
  • 它是一个 Sql 插入命令,可以将新条目放入数据库表中 - 这很有效 - 因为每次尝试都成功地将数据插入到数据库中,但我无法检索 SQL 服务器创建的 ID。
  • @PJW 你不想在同一个Command 中使用SCOPE_IDENTITY() 作为第二个语句。
  • @PJW 关于具体的转换问题,我怀疑@@IDENTITY 正在返回null,不能转换为int
  • @@Idnetity 永远不应该用于返回刚刚插入的身份,如果有人将触发器放在插入另一个表的不完整表上,它将给出磨损的答案。更糟糕的是,除非您的数据被设置为超出您的修复能力,否则您不会发现这一点。所以即使你现在没有触发器,使用@@identity 也是一种极其危险的做法。
【解决方案2】:

事实证明,正确的答案是 SELECT SCOPE_IDENTITY() 语句必须与之前的 INSERT 语句构成同一 SqlCommand 的一部分,但我已包含在之前的 SqlCommand 'pSqlCom' 中。一旦将 SELECT SCOPE_IDENTITY() 作为 pSqlCom 的一部分包含在内,代码就会正确返回标识。

【讨论】:

    【解决方案3】:

    您对命令的调用应该返回非标量类型的内容。事实上,你需要使用 Int32 来代替。 MSDN 上的 Chek ExecuteScalar

    另外,我建议您使用SCOPE_IDENTITY() 而不是@@Identity。查看following link了解详细说明。

    【讨论】:

    • 如果ID是整数,怎么可能不是标量?我也开始使用 SCOPE_INDENTITY() 并收到相同的错误消息,所以我恢复为 @@IDENTITY 作为第二个选项 - 但我没有进一步。
    • 三思而后行。我可以对你的问题做同样的事情,因为它表示缺乏研究。但我更喜欢回答和帮助。再次检查我的答案
    • (Int32) cmd.ExecuteScalar();(int) cmd.ExecuteScalar(); 是同义词。
    • @Yaroslav - 您的回答表明 OP 需要“改用 Int32”我只是指出这将产生零差异。 int 只是同一事物的 C# 关键字。
    • @Yaroslav 据我所知,这些链接并不真正支持您的案例。
    猜你喜欢
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多