SQL觸發器中調用EXE程序碰到的問題總結(SQL觸發器中調用外部程序通過EF更新數據)


DROP  TRIGGER [tritest]

USE Question
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[tritest]
ON [dbo].Question AFTER INSERT
AS
BEGIN    
    DECLARE @Result VARCHAR(100) --如果Id是GUID  GUID不是VARCHAR類型  這裏就給他設置成VARCHAR 1000長度
    SET @Result = 'cmd.exe start /k E:\Code\C#\Info\蘇阿姨打印\Bet\bin\Debug\Bet.exe  ' + CAST((SELECT Id FROM inserted) AS NVARCHAR)   --設置外部程序路徑
    PRINT @Result
    EXEC master..xp_cmdshell @Result --調用外部程序
    SET NOCOUNT ON;
END
GO

有些服務器沒有開啓 xp_cmdshell,執行下面代碼開啓

--開啓xp_cmdshell:
EXEC sp_configure 'show advanced options', 1; 
RECONFIGURE; 
EXEC sp_configure 'xp_cmdshell', 1; 
RECONFIGURE; 
EXEC sp_configure 'show advanced options', 0; 
RECONFIGURE;

 

可以先寫死路徑和Id單獨執行下面這句進行測試

 EXEC master..xp_cmdshell '路徑:\:'

如果還是出現設備未響應或者設備未就緒可能是服務器缺補丁,網上搜下錯誤代碼安裝下安裝包

 

接下來是觸發器和EF配合時碰到的問題

問題1:

接下來碰到了觸發器的問題,我的觸發條件是insert after,按理說數據在表中才會觸發,結果發現觸發器不管是Before還是after觸發時表中都不會有數據,觸發器中的inserted表是系統自帶的,插入操作顯示添加到數據庫再執行觸發器的before和after纔會把系統表inserted表中的數據插入到指定表中.

結論:插入數據顯示插入到inserted表中(系統自帶),再運行觸發器insert before,在運行insert after.

而且觸發器執行應用程序是同步的,會等返回,應用程序sleep5秒觸發器也會等待5秒.

問題2:

觸發器after觸發後調用應用程序,並且傳了ID ,應用程序接受到Id在EF環境下根據ID查詢結果發現沒有值,原因其實在問題1中,Id值是產生了,但是在系統表中,如果在觸發器觸發過程中查詢他還沒有完成添加.

問題3:

在cmd中開啓線程,並且isbackground設置成後臺運行,發現線程不會執行.如果設置成false,他還是同步運行,會把代碼全部執行完觸發器纔算結束. 後臺運行沒有執行的原因:主窗體消失後線程也跟着消失了.

最後的解決方法:

我在數據庫中調用了外部程序1中發送UDP:

 UdpClient uc = new UdpClient();
 IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8899); 
 uc.Send(Encoding.ASCII.GetBytes(param), Encoding.ASCII.GetBytes(param).Length, iep);

再開個外部程序2接收:

 IPAddress localIP = IPAddress.Parse("127.0.0.1");
 IPEndPoint localIPEndPoint = new IPEndPoint(localIP, 8899);
 uc = new UdpClient(localIPEndPoint);
 Thread threadReceive = new Thread(myStaticThreadMethod);
 threadReceive.IsBackground = true;
 threadReceive.Start();



 public static void myStaticThreadMethod()
        {
            IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
                try
                {
                    byte[] receiveBytes = uc.Receive(ref remoteIPEndPoint);
                    string message = Encoding.ASCII.GetString(receiveBytes, 0, receiveBytes.Length);
                    WriteLogs(" succ" + message);
                    Console.WriteLine(" succ" + message);
                    Print(message);
                }
                catch (Exception ex)
                {
                    WriteLogs(ex.ToString());
                    break;
                }
            }
        }

因爲UDP他是沒有交互的,所以只管發不管結果.這樣就解決了同步無法查詢的問題.如果還出現外部程序2無法查詢,可以在外部程序2中暫停幾秒進行查詢.

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章