我有一个强类型数据集,它使用DBDirectMethods通过调用存储过程将数据插入数据库。存储过程返回新创建的记录的主键。这是一个示例存储过程:
CREATE PROCEDURE dbo.CreateUser
(
@UserName VARCHAR(50)
@Password VARCHAR(50)
)
AS
SET NOCOUNT OFF
DECLARE @UserID INT
BEGIN TRANSACTION
INSERT INTO dbo.Users (UserName, Password) VALUES (@UserName, @Password)
SET @UserID = SCOPE_IDENTITY()
INSERT INTO dbo.Users_History (UserID, Status, TimeStamp) VALUES (@UserID, 'C', GETUTCDATE())
COMMIT TRANSACTION
RETURN @UserID
GO
如果我从SSMS执行存储过程,则会创建用户帐户,更新历史记录表,并返回主键。如果我使用强类型数据集运行我的应用程序并让SQL Profiler打勾,我可以看到正在执行相同的代码;但是,数据集返回-1作为主键并中断应用程序。
在VS生成的表适配器代码中,相关的行是:
this._adapter.InsertCommand.CommandText = "dbo.CreateUser";
this._adapter.InsertCommand.CommandType = global::System.Data.CommandType.StoredProcedure;
this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@RETURN_VALUE", global::System.Data.SqlDbType.Int, 4, global::System.Data.ParameterDirection.ReturnValue, 10, 0, null, global::System.Data.DataRowVersion.Current, false, null, "", "", ""));
this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@UserName", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Current, false, null, "", "", ""));
this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Password", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "Password", global::System.Data.DataRowVersion.Current, false, null, "", "", ""));
和
try {
int returnValue = this.Adapter.InsertCommand.ExecuteNonQuery();
return returnValue;
}
finally {
if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) {
this.Adapter.InsertCommand.Connection.Close();
}
}
这只是VS通常生成的标准样板代码 - 没有任何东西是手工编辑的。它只是没有拿起返回值。
我正在使用SQL 2008 R2 SP1 Express运行Windows 7。
答案 0 :(得分:2)
从内存来看,这里的问题是值ExecuteNonQuery()返回的是受查询影响的行数。
相反,您的返回值应该可以通过以下方式访问:
InsertCommand.Parameters["@RETURN_VALUE"].Value;
或
InsertCommand.Parameters[0].Value;
此外,您可以尝试将返回参数名称更改为@UserID
而不是@RETURN_VALUE
,但它仍然可以正常工作。
答案 1 :(得分:2)
似乎不是只返回PK,而是需要返回整个新记录。通过将我的存储过程更改为以下内容:
CREATE PROCEDURE dbo.CreateUser
(
@UserName VARCHAR(50)
@Password VARCHAR(50)
)
AS
SET NOCOUNT OFF
DECLARE @UserID INT
BEGIN TRANSACTION
INSERT INTO dbo.Users (UserName, Password) VALUES (@UserName, @Password)
SET @UserID = SCOPE_IDENTITY()
INSERT INTO dbo.Users_History (UserID, Status, TimeStamp) VALUES (@UserID, 'C', GETUTCDATE())
COMMIT TRANSACTION
SELECT UserID, UserName, Password FROM dbo.Users WHERE UserID = @UserID
GO
然后ADO.NET自动将返回的结果加载到数据集中,我可以从那里获得UserID。
答案 2 :(得分:0)
您需要将查询类型从ExecuteNonQuery更改为ExecuteScalar 见http://blogs.msdn.com/b/smartclientdata/archive/2005/10/31/returnidentityvaluequery.aspx