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中暂停几秒进行查询.

 

 

 

 

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