问题
I have an Azure mobile service with a custom API and it seems to be making multiple SQL calls. When I look at the log, I am seeing multiple responses coming back from the SP. Some of these are empty returns (no recordset), while one of them is communicating with the SP correctly and returning a recordset.
I know my iOS app is only calling the custom API once.
Here is the custom API:
exports.post = function(request, response) {
var mssql = request.service.mssql;
var params = [request.query.FirstName ,
request.query.LastName ,
request.query.DOB ,
request.query.EmailAddress ,
request.query.PhoneNumber ,
request.query.FacilityID ,
request.query.DiagnosisID,
request.query.GeneratedBy ,
request.query.UserTypeID];
console.log("processregistration params = '%j'", params);
var sql = "exec MyStoredProcName ?, ?, ?, ?, ?, ?, ?, ?, ?";
mssql.query(sql, params, {
success: function(results) {
console.log("results = '%j'", results);
// I had to put this in there to keep it from returning an empty recordset
// back to my iOS app
if (results.length > 0) {
response.send(statusCodes.OK, results);
}
}
});
};
Here is the log:

I know the SP only produces one recordset and testing it directly produces a single recordset. I have been able to band-aid it but putting in an if statement before the response.send
. I have never had to do that before. Any ideas?
EDIT - Here is my SP (posted for carlosfigueira)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
==========================================================================================
Author: LJ Wilson
Create date: 2013-12-07
Description: Processes a new (or existing) user registration
==========================================================================================
Revision History
Date Initials Comments
2013-12-07 LJW Created
2013-12-18 LJW Fixed issue with InvitationCodeID
*/
ALTER PROCEDURE [MyApp].[sp_Process_Registration]
@FirstName VARCHAR(500) ,
@LastName VARCHAR(500) ,
@DOB DATETIME ,
@EmailAddress VARCHAR(500) ,
@PhoneNumber VARCHAR(25) ,
@FacilityID INT ,
@DiagnosisID INT ,
@GeneratedBy NVARCHAR(500) ,
@UserTypeID INT
AS
DECLARE @Timestamp AS DATETIME = CURRENT_TIMESTAMP
DECLARE @ExistingUserID AS INT = ( SELECT ID
FROM MyApp.Users
WHERE UserTypeID = @UserTypeID
AND EmailAddress = @EmailAddress
AND LastName = @LastName
)
DECLARE @EmailAddressInUse AS INT = ( SELECT COUNT(ID)
FROM MyApp.Users
WHERE EmailAddress = @EmailAddress
)
IF @ExistingUserID IS NULL
BEGIN
BEGIN TRAN
INSERT INTO MyApp.Users
( LoginName ,
FriendlyName ,
JoinDate ,
PhoneNumber ,
EmailAddress ,
UserTypeID ,
IsActive ,
FacilitiesListID ,
AllowTexting ,
AllowEmail ,
AllowCalls ,
AllowAPNS ,
ImagePath ,
ShowImage ,
LastUpdatedBy ,
LastUpdatedOn ,
FirstName ,
LastName ,
DOB
)
VALUES ( @EmailAddress , -- LoginName - nvarchar(250)
NULL , -- FriendlyName - nvarchar(500)
@Timestamp , -- JoinDate - datetime
@PhoneNumber , -- PhoneNumber - nvarchar(50)
@EmailAddress , -- EmailAddress - nvarchar(500)
@UserTypeID , -- UserTypeID - smallint
1 , -- IsActive - bit
NULL , -- FacilitiesListID - int
NULL , -- AllowTexting - bit
1 , -- AllowEmail - bit
NULL , -- AllowCalls - bit
1 , -- AllowAPNS - bit
NULL , -- ImagePath - nvarchar(1000)
NULL , -- ShowImage - bit
@GeneratedBy , -- LastUpdatedBy - nvarchar(500)
@TimeStamp , -- LastUpdatedOn - datetime
@FirstName , -- FirstName - varchar(500)
@LastName , -- LastName - varchar(500)
@DOB -- DOB - datetime
)
COMMIT TRAN
SET @ExistingUserID = ( SELECT @@IDENTITY
)
END
BEGIN
DECLARE @InvitationCode AS VARCHAR(50) = ( SELECT dbo.fnc_GenInvitationCode(@EmailAddress,
@FacilityID,
@DiagnosisID)
)
INSERT INTO MyApp.InvitationCodes
( InvitationCode ,
UserID ,
FacilityID ,
InvitationGeneratedOn ,
GeneratedBy ,
DiagnosisIdentifier ,
InvitationActive
)
VALUES ( @InvitationCode , -- InvitationCode - nvarchar(50)
@ExistingUserID , -- UserID - int
@FacilityID , -- FacilityID - int
@Timestamp , -- InvitationGeneratedOn - datetime
@GeneratedBy , -- GeneratedBy - nvarchar(500)
@DiagnosisID , -- DiagnosisIdentifier - int
NULL -- InvitationActive - bit
)
END
DECLARE @InvitationCodeID AS INT = ( SELECT ID
FROM MyApp.InvitationCodes
WHERE InvitationCode = @InvitationCode
AND InvitationGeneratedOn = @Timestamp
)
INSERT INTO MyApp.FacilitiesList
( UserID ,
InvitationCodeID ,
FacilityID ,
AddedOn ,
AddedBy
)
VALUES ( @ExistingUserID , -- UserID - int
@InvitationCodeID , -- InvitationCodeID - int
@FacilityID , -- FacilityID - int
@Timestamp , -- AddedOn - datetime
@GeneratedBy -- AddedBy - nvarchar(500)
)
SELECT @InvitationCode AS InvitationCode ,
@EmailAddressInUse AS EmailAddressInUse ,
@ExistingUserID AS ExistingUserID
GO
回答1:
The issue you're having is that your stored procedure is executing lots of intermediate operations (query for existing user id, query for e-mail address in use, etc.), and by default all of those operations are returned as result sets by the SQL server, which is why you're seeing those empty result sets before the "real" one.
You can use the SET NOCOUNT ON
statement in your stored procedure, and that will effectively remove those intermediate SQL executions from the list of result sets which is returned to the mssql.query
function. Your SPROC would look like this
ALTER PROCEDURE [carlosfigueira].[sp_Process_Registration]
@FirstName VARCHAR(500) ,
@LastName VARCHAR(500) ,
@DOB DATETIME ,
@EmailAddress VARCHAR(500) ,
@PhoneNumber VARCHAR(25) ,
@FacilityID INT ,
@DiagnosisID INT ,
@GeneratedBy NVARCHAR(500) ,
@UserTypeID INT
AS
SET NOCOUNT ON
DECLARE @Timestamp AS DATETIME = CURRENT_TIMESTAMP
-- rest of the stored proc code is the same
Once you add that statement, the callback passed to mssql.query
will only be invoked once.
来源:https://stackoverflow.com/questions/20726274/azure-mobile-service-custom-api-calling-sql-sp-multiple-times