1

I have a controller that receives a list of objects. First it checks if any of these objects already exists in the table by using ExecuteScalar. If rows already exist, we run the Update stored procedure. If not, we run the Insert stored procedure. However, my code fails at the Execute Scalar function which tells us 'Must declare the scalar variable @DeviceId'. I'm not sure if the error message is referring to the query or the Sql Parameters.

 public BaseResponse Post([FromBody]List<PendingAttachment> pendingAttachmentRequest)
    {
        PendingAttachment pendingAttachment = new PendingAttachment();
        List<SqlParameter> sqlParameters = new List<SqlParameter>() 
        {
            new SqlParameter("@Datasource", pendingAttachment.DataSource),
            new SqlParameter("@LastUpdated", pendingAttachment.LastUpdated),
            new SqlParameter("@PendingCount", pendingAttachment.PendingCount),
            new SqlParameter("@DeviceId", pendingAttachment.DeviceId),
            new SqlParameter("@Username", pendingAttachment.UserName),
        };
        try
        {           
            RequestHeaders headers = new RequestHeaders();
            var query = "SELECT count(*) FROM PendingAttachments WHERE DeviceId = @DeviceId AND UserName = @UserName";
            using (var onbaseConnection = MobileCompleteServer.Helpers.OnbaseAuth.Connect(headers))
            {
                var connectionString = System.Configuration.ConfigurationManager.AppSettings["ConnectionString"];

                using (SqlConnection sqlConnection = new SqlConnection(connectionString))
                {
                    sqlConnection.Open();
                    using (SqlCommand comm = new SqlCommand(query, sqlConnection))
                    {
                        comm.CommandType = System.Data.CommandType.Text;
                        foreach(PendingAttachment attachment in pendingAttachmentRequest)
                        {
                            
                            comm.Parameters.AddRange(sqlParameters.ToArray());
                            comm.Parameters.Clear();
                        }
                        int rowCount = (int)comm.ExecuteScalar();   //FAILS HERE
                        if (rowCount > 0)
                        {
                            using (SqlCommand sqlComm = new SqlCommand("sp_UpdatePendingAttachments", sqlConnection))
                            {
                                sqlComm.CommandType = System.Data.CommandType.StoredProcedure;
                                foreach (PendingAttachment attachment in pendingAttachmentRequest)
                                {
                                    
                                    sqlComm.Parameters.AddRange(sqlParameters.ToArray());
                                    sqlComm.Parameters.Clear();
                                }
                                sqlComm.ExecuteNonQuery();
                            }
                        }
                        else
                        {
                            using (SqlCommand sqlCommand = new SqlCommand("sp_InsertPendingAttachments", sqlConnection))
                            {
                                sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
                                foreach(PendingAttachment attachment in pendingAttachmentRequest)
                                {
                                    
                                    sqlCommand.Parameters.AddRange(sqlParameters.ToArray());
                                    sqlCommand.Parameters.Clear();
                                }
                                sqlCommand.ExecuteNonQuery();
                            }
                        }
                    }
                }
                return new BaseResponse();
            }
        }
        catch (Exception ex)
        {
                return new BaseResponse
                {
                    Exception = ErrorCodes.Get(ex, ErrorCodes.PendingAttachmentError),
                    ExceptionStackTrace = ex.ToString()
                };
            

        }
    }
}
Gabriel
  • 346
  • 5
  • 24
  • 1
    you are doing `sqlComm.Parameters.Clear();` after each `sqlCommand.Parameters.AddRange(...)` - so... it won't have any parameters? did you mean to do `sqlParameters.Clear()` ? – Marc Gravell Sep 09 '20 at 16:09
  • unrelated: ADO.NET has a very unfriendly and verbose API; tools like Dapper can make invoking SQL *much much easier and safer*; consider: `var rowCount = (int) onbaseConnection.ExecuteScalar(@" SELECT count(*) FROM PendingAttachments WHERE DeviceId = @DeviceId AND UserName = @UserName", new { Datasource = pendingAttachment.DataSource, pendingAttachment.LastUpdated, pendingAttachment.PendingCount, pendingAttachment.DeviceId, Username = pendingAttachment.UserName });` – Marc Gravell Sep 09 '20 at 16:10
  • I did that so you dont try to use a parameter that has already been declared while going through the foreach() – Gabriel Sep 09 '20 at 16:11
  • but... that isn't what it does; what it *does* is: remove all the parameters from the command, so: zero parameters; also - why does it loop over the attachments without executing something inside that loop? – Marc Gravell Sep 09 '20 at 16:13
  • I moved the Clear and this is the new error: + ex {"The parameterized query '(@Datasource nvarchar(4000),@LastUpdated nvarchar(4000),@Pending' expects the parameter '@Datasource', which was not supplied."} System.Exception {System.Data.SqlClient.SqlException} – Gabriel Sep 09 '20 at 16:19
  • was the .Value `null` by and chance? (If it was: that's an easy fix; amusingly I actually posted the how as an answer before I saw the Clear() problem). So if it is `null`, let me know and I'll undelete my answer! – Marc Gravell Sep 09 '20 at 19:42

0 Answers0