简体   繁体   English

C# 向存储过程调用添加额外/不需要的参数

[英]C# adding extra/unwanted parameters to stored procedure call

I have a strange problem that is happening.我有一个奇怪的问题正在发生。 On my development system everything runs fine but running the code on the production system it is adding extra parameters.在我的开发系统上一切正常,但在生产系统上运行代码会添加额外的参数。 Here is the code.这是代码。

        public string Read(Setting SettingID, string SettingValue, int GameID)
        {
            SqlCommand sqlText;
            string SettingName = SettingsNames[(int)SettingID];

            using (SqlConnection cn = new SqlConnection(DataHandlers.ConnString))
            {
                sqlText = cn.CreateCommand();

                sqlText.CommandType = CommandType.StoredProcedure;
                sqlText.CommandText = "Proc_Settings";
                sqlText.Parameters.Clear();
                sqlText.Parameters.Add(new SqlParameter("SettingName", SettingName));
                sqlText.Parameters.Add(new SqlParameter("SettingValue", SettingValue));
                sqlText.Parameters.Add(new SqlParameter("Dir", Direction.Read));
                sqlText.Parameters.Add(new SqlParameter("GameID", GameID));
                sqlText.Parameters.Add("@Return", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;

![文字](E://pulltab/capture.png)

The first 2 parameters add fine.前 2 个参数添加得很好。 On the third parameter is adds 'DIR' and @Return but @Return is an input.在第三个参数上添加 'DIR' 和 @Return 但 @Return 是一个输入。 the same happens for the 4th parameter and then it adds the 5th as a return.第 4 个参数也会发生同样的情况,然后添加第 5 个参数作为返回值。 The function is being called from another thread when the issue happens.问题发生时,正在从另一个线程调用该函数。 The thread is a com port handler.该线程是一个 com 端口处理程序。 If I disable the com ports in bios it works fine, this makes sense since my dev computer does not have the same number of ports so the one for the device is missing.如果我禁用 bios 中的 com 端口,它工作正常,这是有道理的,因为我的开发计算机没有相同数量的端口,因此缺少设备的端口。 Once I enable the ports and the routine starts up the polling thread is when the issue begins.一旦我启用端口并且例程启动,轮询线程就是问题开始的时候。 I have looked at the different threads in VS and the only one that takes me to code related to the issue is the current one I am debugging.我查看了 VS 中的不同线程,唯一让我了解与该问题相关的代码的是我正在调试的当前线程。 Am I causing a threading violation here?我是否在这里造成线程违规?

this is the poll routine这是轮询例程

        private void Poll()
        {
            Actions.init(buffer, length, ComDll, Port);             //Function to Initialize

            while (Active)
            {
                // Process the com port
                // Currently doesn't get here
            }
         }

And here is the init function,这是 init 函数,

        public static void init(byte[] buffer, int length, ID003CommandCreater ComDll, SerialPort Port)
        {
            byte enable1 = 0;
            byte enable2 = 0;
            byte[] status = new byte[255]; //Buffer to read data from the serial port
            bool initializing = true;

            while (initializing)
            {
                try
                {
                    // Initializes the device
                    ComDll.Reset(buffer);
                    length = (int)buffer[1];
                    Port.Write(buffer, 0, length);
                    System.Threading.Thread.Sleep(3000);
                    Port.Read(status, 0, 255);               //Fails when device not connected

                    … More init commands sent

                    initializing = false;
                }
                catch
                {
                    if (Port.PortName != settings.Read(Settings.Setting.ComPort, Port.PortName, 0))
                    {
                        Port.Close();
                        initializing = false;
                    }
                    //JCM.BVstatus = "Com Failure";
                    //JCM.bvComFailure = true;
                }
            }
        }

Here is the error.这是错误。

"System.Data.SqlClient.SqlException (0x80131904): Procedure or function Proc_Settings has too many arguments specified.\\nProcedure or function Proc_Settings has too many arguments specified.\\r\\n at System.Data.SqlClient.SqlConnection.OnError (System.Data.SqlClient.SqlException exception, System.Boolean breakConnection, System.Action 1[T] wrapCloseInAction) [0x0004c] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlConnection.OnError(System.Data.SqlClient.SqlException,bool,System.Action 1<System.Action>)\\r\\n at System.Data.SqlClient.SqlInternalConnection.OnError (System.Data.SqlClient.SqlException exception, System.Boolean breakConnection, System.Action 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource "System.Data.SqlClient.SqlException (0x80131904):过程或函数 Proc_Settings 指定的参数过多。\\n过程或函数 Proc_Settings 指定的参数过多。\\r\\n 在 System.Data.SqlClient.SqlConnection.OnError (System. Data.SqlClient.SqlException 异常,System.Boolean breakConnection,System.Action 1[T] wrapCloseInAction) [0x0004c] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlConnection.OnError(System.Data.SqlClient.SqlException,bool,System.Action 1<System.Action>)\\r\\n 在 System.Data.SqlClient.SqlInternalConnection.OnError(System.Data.SqlClient.SqlException 异常,系统.Boolean breakConnection, System.Action 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource 1[TResult] completion, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.String method) [0x00079] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.String method) [0x0000b] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at Sys 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource 1[TResult] 完成、System.Int32 超时、System.Threading.Tasks.Task& 任务、System.Boolean asyncWrite、System.String 方法)[0x00079] 在 <290425a50ff84a639f8c060e2d6>453 r\\n 在 System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.String 方法) [0x0000b] 在 <290425a50ff84a639f8c060e2d4530f6>:0 r\\n 在 Sys tem.Data.SqlClient.SqlCommand.ExecuteReader (System.Data.CommandBehavior behavior) [0x0003c] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.ExecuteReader () [0x0000e] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlCommand.ExecuteReader()\\r\\n at Settings.Read (Settings+Setting SettingID, System.String SettingValue, System.Int32 GameID) [0x000cb] in E:\\Unity\\xxxx\\Assets\\xxxx\\Scripts\\Database\\Settings.cs:192 \\r\\nClientConnectionId:42a5adfe-d934-496e-b678-456fde7d2622\\r\\nError Number:8144,State:2,Class:16" tem.Data.SqlClient.SqlCommand.ExecuteReader (System.Data.CommandBehavior 行为) [0x0003c] 在 <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n 在 System.Data.SqlClient.SqlCommand.ExecuteReader () [0x00009040400e] 在 <290425a50ff84a639f8c060e2d4530f6>:0 0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlCommand.ExecuteReader()\\r\\n at Settings.Read (Settings+Setting SettingID, System.String SettingValue, System.Int32 GameID ) [0x000cb] 在 E:\\Unity\\xxxx\\Assets\\xxxx\\Scripts\\Database\\Settings.cs:192 \\r\\nClientConnectionId:42a5adfe-d934-496e-b678-456fde7d2622\\r\\n错误编号:8144,State:2 ,等级:16"

I have used a little threading before but might be misunderstanding some of this.我之前使用过一些线程,但可能会误解其中的一些。 In this case the Init must complete successfully before the poll thread continues.在这种情况下,Init 必须在轮询线程继续之前成功完成。 Once the init is done then the thread will enter a loop to handle the com port.初始化完成后,线程将进入一个循环来处理 com 端口。 If I do not wait on the hardware then the loop will try to send more data from the com port which will mess up the configuration.如果我不等待硬件,那么循环将尝试从 com 端口发送更多数据,这会破坏配置。 There are about 6 steps that I must do in a sequence to successfully initialize the hardware.为了成功初始化硬件,我必须按顺序执行大约 6 个步骤。 That first command resets the device and it takes just short of 3 seconds for it to initialize before I can continue talking to it.第一个命令会重置设备,在我可以继续与它交谈之前,它只需要 3 秒钟就可以初始化。 Do i want the thread to continue?我希望线程继续吗? This thread only runs the code for the device, nothing else.这个线程只运行设备的代码,没有别的。 All of the other code continues.所有其他代码继续。 The Read routine is called from multiple threads. Read 例程是从多个线程调用的。 It is used throughout the program.它在整个程序中使用。

When you use System.Threading.Thread.Sleep(3000);当你使用System.Threading.Thread.Sleep(3000); you block the current thread as a means to wait for the task to finish and that can result in deadlocks and blocked context threads您阻塞当前线程作为等待任务完成的一种方式,这可能导致死锁和阻塞的上下文线程

When you wait for a certain amount of time you should rather wait with await System.Threading.Tasks.Task.Delay(3000);当您等待一定的时间时,您应该使用await System.Threading.Tasks.Task.Delay(3000); . . Because this command doesn't block the current thread.因为这个命令不会阻塞当前线程。

To use this command you need to make your method asynchronous.要使用此命令,您需要使您的方法异步。

Your Code made asynchronous:您的代码异步:

public static async System.Threading.Tasks.Task InitAsync(
    byte[] buffer,
    int length,
    ID003CommandCreater ComDll,
    SerialPort Port) 
{
    byte enable1 = 0;
    byte enable2 = 0;
    byte[] status = new byte[255]; //Buffer to read data from the serial port
    bool initializing = true;

    while (initializing) {
        try {
            // Initializes the device
            ComDll.Reset(buffer);
            length = (int)buffer[1];
            Port.Write(buffer, 0, length);

            // Doesn't block thread anymore, because we wait until the task is finished.
            await System.Threading.Tasks.Task.Delay(300);
            Port.Read(status, 0, 255);

            … More init commands sent

            initializing = false;
        }
        catch {
            if (Port.PortName != settings.Read(Settings.Setting.ComPort, Port.PortName, 0)) {
                Port.Close();
                initializing = false;
            }
            //JCM.BVstatus = "Com Failure";
            //JCM.bvComFailure = true;
        }
    }
}

I would advise you to make methods that call this method asynchronous as well but if that is not possible, then you need to ensure that there are no deadlocks and that is possible with a small workaround.我建议您也创建异步调用此方法的方法,但如果这是不可能的,那么您需要确保没有死锁,并且可以通过一个小的解决方法来实现。

To call a asynchronous method in a synchronous method we first need to add a class that clears the thread so we don't block it要在同步方法中调用异步方法,我们首先需要添加一个清除线程的类,这样我们就不会阻塞它

NoSynchronizationContextScope Class: NoSynchronizationContextScope 类:

public static class NoSynchronizationContextScope {
    public static Disposable Enter() {
        var context = SynchronizationContext.Current;
        SynchronizationContext.SetSynchronizationContext(null);
        return new Disposable(context);
    }

    public struct Disposable : IDisposable {
        private readonly SynchronizationContext _synchronizationContext;

        public Disposable(SynchronizationContext synchronizationContext) {
            _synchronizationContext = synchronizationContext;
        }

        public void Dispose() =>
            SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
    }
}

Now we can call asynchronous method anywhere in our code if we use these lines of code.现在,如果我们使用这些代码行,我们可以在代码中的任何地方调用异步方法。

Calling Asynchronous method in a synchronous method:在同步方法中调用异步方法:

private void MySynchronousMethodLikeDisposeForExample() {
    using (NoSynchronizationContextScope.Enter()) {
        InitAsync().Wait();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM