无法在windows服务中执行SQL命令

无法在windows服务中执行SQL命令,sql,vb.net,ado.net,windows-services,Sql,Vb.net,Ado.net,Windows Services,我正在创建一个windows服务,当客户提交的邮件在一个月内过期时,该服务将向客户发送电子邮件。我正在Visual Studio 2008中使用vb.net 因为它是windows服务,所以调试非常困难。为了缩小我的错误范围,我创建了一个“sendDebugEmail”方法,如果到达某一行,它会向我发送一封电子邮件。电子邮件永远不会通过“dr=cmd.ExecuteReader() 我想知道我做错了什么。我的SQL语句应该可以正常工作。我已经在我的SQL server数据库中对其进行了测试 我已

我正在创建一个windows服务,当客户提交的邮件在一个月内过期时,该服务将向客户发送电子邮件。我正在Visual Studio 2008中使用vb.net

因为它是windows服务,所以调试非常困难。为了缩小我的错误范围,我创建了一个“sendDebugEmail”方法,如果到达某一行,它会向我发送一封电子邮件。电子邮件永远不会通过“dr=cmd.ExecuteReader()

我想知道我做错了什么。我的SQL语句应该可以正常工作。我已经在我的SQL server数据库中对其进行了测试

我已经创建了一个虚拟_数据库,这也是我刚刚在SQLServer中创建的。我为其中的虚拟表添加了一条INSERT sql语句,只是想看看是否可以访问数据库。该表只接收行号和发送时间。当我运行我的windows服务时,数据库更新很好

任何帮助都将不胜感激。谢谢

Dim conn As New SqlConnection(connString2)

    sendDebugEmail("134")

    SQL = "Select email FROM _Customer WHERE custID in (SELECT custID FROM _OnlineCustomer WHERE ExpirationDate <= '6-20-12' AND ExpirationDate >= '6-10-12')"
    Dim cmd As New SqlCommand(SQL, conn)


    sSubject = "hello"
    sBody = "This is test data"
    Dim dr As SqlDataReader

    sendDebugEmail("143")

    Try
        dr = cmd.ExecuteReader()   // This is were it stops

        sendDebugEmail("147")

        While dr.Read

            sendDebugEmail("152")

            Try
                LogInfo("Service woke up")
                Dim i As Integer = 0
                ' Prepare e-mail fields
                sFrom = "test@gmail.com"
                sTo = "test1@gmail.com"
                sCc = "test2@gmail.com"
                Dim oMailMsg As MailMessage = New MailMessage
                oMailMsg.From = sFrom
                oMailMsg.To = sTo
                oMailMsg.Cc = sCc
                ' Call a stored procedure to process the current item
                ' The success message
                oMailMsg.Subject = sSubject + "(Success)"
                oMailMsg.Body = sBody + "Email has been sent successfully."
                ' Send the message
                If Not (oMailMsg.To = String.Empty) Then
                    SmtpMail.Send(oMailMsg)
                End If

            Catch obug As Exception
                LogEvent(obug.Message)
            Finally

            End Try
        End While
    Catch ex As Exception

    Finally
        dr.Close()
        cmd.Dispose()
        conn.Close()
        conn.Dispose()
    End Try
End Sub

它向我发送了一封stackTrace的电子邮件,使调试变得非常容易

您是否捕获和接受异常?如果你是,停下来。让异常服务使服务崩溃:异常将记录在事件日志中。您应该捕获的唯一异常是那些您实际上可以从中恢复的异常(尽管捕获异常、记录异常并通过
throw;
重新播放异常是有效的)

您是否使用log4net插入了代码(http://logging.apache.org/log4net/),还是类似的?您应该这样做,特别是对于像Windows服务这样的守护进程—当出现问题时(正如它们将要发生的那样),您(或操作)还将如何诊断服务的问题

编辑如下:

  • 您应该使用
    语句:所有这些ADO.Net对象都是
    IDisposable
    。它使代码更清晰

  • 考虑使用SqlDataAdapter用结果集填充数据表或数据集。您正在使用的模式:

    read a row from SQL
    while read was successful
      send an email
      read a row from SQL
    
    最终会导致数据库阻塞。与邮件服务器交谈可能会导致高延迟。如果邮件服务器没有应答,或者您有网络拥塞,或者其他任何原因,您将被挂起,直到邮件发送或由于超时引发异常为止。您的SQL查询将在表和索引上设置读锁,从中读取数据,阻止人们尝试进行更新、插入或删除。您的生产DBA将…烦恼。你想保持你的锁移动,并尽快释放锁


  • 还有一个建议是,在进程启动时在进程上添加一个sleep语句,这样您就有时间附加到它了

    如果您确信自己的代码(没有例外),我认为您应该检查用于连接SQL server的身份验证(位于windows服务的app.config文件/内联代码中的连接字符串内)

    如果对此使用SQL身份验证(检查用户名sa及其密码的连接字符串),将windows服务的帐户类型设置为LocalService将对您有所帮助

    如果SQL连接使用windows身份验证,则将windows服务的帐户类型设置为LocalSystem将对您有所帮助

    帐户类型修改也可以在安装后进行。为此,请转到“控制面板”->“管理工具”->“服务”->“您的服务”-右键单击并选择“属性”->“登录”->,然后在那里执行。如果您选择的是本地系统(windows身份验证)系统将要求您输入运行服务的帐户的登录凭据

    对于SQL连接中的windows身份验证,运行服务的帐户的凭据也将用于SQL连接

    希望这有帮助……

    问题解决了:我设置了连接,但从未打开过连接。
    我需要控制室开门

    对我帮助最大的是将以下代码添加到我的上一个catch语句中:

    sendDebugEmail(ex.Message & vbcrlf & ex.stackTrace)
    
    sendDebugEmail(ex.Message & vbcrlf & ex.stackTrace)
    

    它向我发送了一封stackTrace的电子邮件,使调试变得非常容易

    您的连接字符串是什么样子?我的猜测是:用于登录SQL Server的用户/帐户没有必要的权限…对,正如@marc_s所说,如果服务在本地服务帐户下运行,它将无法访问远程资源,类似SQL Server数据库。若要调试服务,请启动它。然后在Visual Studio中,选择“调试”->“附加到进程”。找到服务进程并附加到进程。然后您可以将其作为任何应用程序进行调试。您可以设置断点和所有内容。我认为这会有所帮助。@Mikael,我使用的是Visual Studio 2008。它没有附加到进程的功能将进程发送到调试器。至少不是这样。哦,我明白了。这是一样的,只是路径是Debug->processs。单击服务进程,然后附加。你是说我不需要我的第一个Try/Catch语句吗?+1非常好的注释。另外:你可以使用udpapender for log4net,然后使用UDP接收器(如Log4View)来监视实时记录条目。您的第一个捕获捕获捕获(并吞咽)它捕获的任何异常并记录其消息,而不记录其周围的任何上下文(异常类型、堆栈跟踪、内部异常数据等)。您的外部异常将只捕获由
    ExecuteReader()引发的异常
    …它只是吞没了它,而不记录任何关于它的信息。只处理你实际上可以从中恢复的异常。捕获一个日志记录一个发送电子邮件的异常是可以的,只需将挂起的电子邮件留在队列中,这样它就可以重新发送。这样,一封失败的电子邮件不会扼杀整个过程。所以我是vb.net的新手。将使用sqlDataAdapter为我提供了一系列即将过期的电子邮件地址?这就是我最终想要得到的。我正试图让它逐一浏览每个电子邮件地址,并将其删除