Windows 使用 VB.NET 的服务不起作用?
Windows service using VB.NET doesn't work?
我的程序应该做什么:我的目标是创建一个 windows 服务作为多个 SQL 数据库之间的中介。在 3 个不同的服务器中总共有 3 个不同的 tables 具体来说,当此服务运行时,它应该监督“Table1”中的数据并定期(每 1 分钟)将其复制到“Table2”。但棘手的部分是它不能粘贴重复记录,必须检查“Table2”的 ID 字段并验证是否粘贴具有相同 ID 的相同记录。I've added a diagram for understanding purposes of what my goal is
我所做的:到目前为止,我已经完全开发了代码,但问题是它只从一个 table(特别是“NOR_LABOR”根据我附上的图表)到“MES_DEV”数据库中的“DEV_Test_Nor_Data”(con1 到 con2)。根据图con1、con3、con4分别是tables“NOR_LABOR”、“SETTER_LABOR”和“wrap_labor”。 con2 是“MES_DEV”DB 的目的地。
有人能弄清楚为什么其他 table 的数据(con3 到 con2 和 con4 到 con2)不能复制吗?
我的代码 - 数据收集器
Imports System.Configuration
Imports System.Data.SqlClient
Public Class DataCollector
Dim con1, con2, con3, con4 As New SqlConnection
Dim timer1 As Timers.Timer
Dim p_oConn As New Wisys.AllSystem.ConnectionInfo
Protected Overrides Sub OnStart(ByVal args() As String)
con1 = New SqlConnection("Data Source=NORMAC-CTMS\SQLEXPRESS;Database=Normac Data;Integrated Security=true")
con1.Open()
con2 = New SqlConnection("Data Source=STLEDGSQL01;Database=MES_DEV;Integrated Security=true")
con2.Open()
con3 = New SqlConnection("Data Source=201706-SETTER1\SQLEXPRESS;Database=Edge;Integrated Security=true")
con3.Open()
con4 = New SqlConnection("Data Source=PRINTER\SQLEXPRESS;Database=Wrapper Data;Integrated Security=true")
con4.Open()
timer1 = New Timers.Timer()
timer1.Interval = 5000
AddHandler timer1.Elapsed, AddressOf OnTimedEvent
timer1.Enabled = True
FileIO.WriteLog("Service has started")
End Sub
Protected Overrides Sub OnStop()
timer1.Enabled = False
FileIO.WriteLog("Service has stopped")
con1.Close()
con2.Close()
con3.Close()
con4.Close()
End Sub
Private Sub OnTimedEvent(obj As Object, e As EventArgs)
Dim cmd1, cmd2, cmd3 As SqlCommand
'Connecting the Normac Data table
Dim da1 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, feet_produced, item_no, posted, labor_feet_produced from NOR_LABOR", con1)
Dim cb1 As SqlCommandBuilder = New SqlCommandBuilder(da1)
Dim dt1 As DataTable = New DataTable()
da1.Fill(dt1)
'Connecting the Setter_Labor table
Dim da2 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, labor_feet_produced, item_no, posted from Setter_Labor", con3)
Dim cb2 As SqlCommandBuilder = New SqlCommandBuilder(da2)
Dim dt2 As DataTable = New DataTable()
da2.Fill(dt2)
'Connecting the Wrap_Labor table
Dim da3 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, Department, work_center, operation_no, operator, total_labor_hrs, job_start, job_end, qty_ordered, qty_produced, item_no, lot_no, default_bin, posted, wrapped, total_shift_hrs, check_emp, machine, operation_complete from wrap_labor", con4)
Dim cb3 As SqlCommandBuilder = New SqlCommandBuilder(da3)
Dim dt3 As DataTable = New DataTable()
da3.Fill(dt3)
Dim i, j, k As Integer
'Inserting into DEV_Test_Nor_Data table
For Each dr As DataRow In dt1.Rows
cmd1 = New SqlCommand("Insert into DEV_Test_Nor_Data values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "','" & dr(11) & "')", con2)
i = cmd1.ExecuteNonQuery()
Next
'Inserting into DEV_Test_Set_Lbr table
For Each dr As DataRow In dt2.Rows
cmd2 = New SqlCommand("Insert into DEV_Test_Set_Lbr values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "')", con2)
j = cmd2.ExecuteNonQuery()
Next
'Inserting into DEV_Test_Wrp_Lbr table
For Each dr As DataRow In dt3.Rows
cmd3 = New SqlCommand("Insert into DEV_Test_Wrp_Lbr values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "','" & dr(11) & "','" & dr(12) & "','" & dr(13) & "','" & dr(14) & "','" & dr(15) & "','" & dr(16) & "','" & dr(17) & "','" & dr(18) & "','" & dr(19) & "','" & dr(20) & "')", con2)
k = cmd3.ExecuteNonQuery()
Next
da1.Update(dt1)
cmd1.Dispose()
dt1.Dispose()
da1.Dispose()
da2.Update(dt2)
cmd2.Dispose()
dt2.Dispose()
da2.Dispose()
da3.Update(dt3)
cmd3.Dispose()
dt3.Dispose()
da3.Dispose()
End Sub
End Class
Reference2
Reference3
Reference4
看看这是否有帮助。可能是参数化查询是你的全部问题。
Public Class DataCollector
'Question text said one minute
Private timer1 As New Timers.Timer(60000)
Protected Overrides Sub OnStart(ByVal args() As String)
AddHandler timer1.Elapsed, AddressOf OnTimedEvent
timer1.Enabled = True
FileIO.WriteLog("Service has started")
End Sub
Protected Overrides Sub OnStop()
timer1.Enabled = False
FileIO.WriteLog("Service has stopped")
End Sub
Private Sub OnTimedEvent(obj As Object, e As EventArgs)
' DEV_Test_Nor_Data Table
ProcessOneTable("DEV_Test_Nor_Data", 12,
"Data Source=NORMAC-CTMS\SQLEXPRESS;Database=Normac Data;Integrated Security=true",
"SELECT ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, feet_produced, item_no, posted, labor_feet_produced FROM NOR_LABOR"
)
' DEV_Test_Set_Lbr Table
ProcessOneTable("DEV_Test_Set_Lbr", 11,
"Data Source=201706-SETTER1\SQLEXPRESS;Database=Edge;Integrated Security=true",
"SELECT ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, labor_feet_produced, item_no, posted from Setter_Labor"
)
' DEV_Test_Wrp_Lbr Table
ProcessOneTable("DEV_Test_Wrp_Lbr", 21,
"Data Source=PRINTER\SQLEXPRESS;Database=Wrapper Data;Integrated Security=true",
"SELECT ID, trx_date, work_order, Department, work_center, operation_no, operator, total_labor_hrs, job_start, job_end, qty_ordered, qty_produced, item_no, lot_no, default_bin, posted, wrapped, total_shift_hrs, check_emp, machine, operation_complete from wrap_labor"
)
End Sub
Private EdgeConnStr As String = "Data Source=STLEDGSQL01;Database=MES_DEV;Integrated Security=true"
Private Sub ProcessOneTable(destTableName As String, ParameterCount As Integer, sourceConnectionString AS String, sourceSql As String)
Dim data As New DataTable()
Using sourceConn As New SqlConnection(sourceConnectionString), _
da As New SqlDataAdapter(sourceSql, sourceConn)
da.Fill(data)
End Using
Dim paramList As String = String.Join(",", Enumerable.Range(0, ParameterCount).Select(Function(p) $"@p{p}"))
' Assumes first parateter (@p0) is always the ID.
Dim sql As String = $"INSERT INTO {destTableName} SELECT {paramList} WHERE NOT EXISTS(SELECT ID FROM {destTableName} WHERE ID = @p0)"
Using cn As New SqlConnection(EdgeConnStr), _
cmd As New SqlCommand(sql, cn)
For i As Integer = 0 To ParameterCount - 1
cmd.Parameters.Add($"@p{i}", SqlDbType.VarChar)
Next i
cn.Open()
For Each dr As DataRow In data.Rows
For i As Integer = 0 to ParameterCount - 1
cmd.Parameters(i).Value = dr(i)
Next i
cmd.ExecuteNonQuery()
Next dr
End Using
End Sub
End Class
听起来您还需要担心 合并 数据,但无论如何都要从这里开始;它修复了原始代码中的 HUGE GAPING SECURITY ISSUE,并将代码的重要部分隔离到尽可能小的方法大小。这将使 仅重构那部分 变得更容易,同时也可以担心哪些 ID 可能已经存在......但我会让你先自己尝试一下(提示:INSERT + SELECT + WHERE NOT EXISTS()
都在同一个查询中)
我的程序应该做什么:我的目标是创建一个 windows 服务作为多个 SQL 数据库之间的中介。在 3 个不同的服务器中总共有 3 个不同的 tables 具体来说,当此服务运行时,它应该监督“Table1”中的数据并定期(每 1 分钟)将其复制到“Table2”。但棘手的部分是它不能粘贴重复记录,必须检查“Table2”的 ID 字段并验证是否粘贴具有相同 ID 的相同记录。I've added a diagram for understanding purposes of what my goal is
我所做的:到目前为止,我已经完全开发了代码,但问题是它只从一个 table(特别是“NOR_LABOR”根据我附上的图表)到“MES_DEV”数据库中的“DEV_Test_Nor_Data”(con1 到 con2)。根据图con1、con3、con4分别是tables“NOR_LABOR”、“SETTER_LABOR”和“wrap_labor”。 con2 是“MES_DEV”DB 的目的地。
有人能弄清楚为什么其他 table 的数据(con3 到 con2 和 con4 到 con2)不能复制吗?
我的代码 - 数据收集器
Imports System.Configuration
Imports System.Data.SqlClient
Public Class DataCollector
Dim con1, con2, con3, con4 As New SqlConnection
Dim timer1 As Timers.Timer
Dim p_oConn As New Wisys.AllSystem.ConnectionInfo
Protected Overrides Sub OnStart(ByVal args() As String)
con1 = New SqlConnection("Data Source=NORMAC-CTMS\SQLEXPRESS;Database=Normac Data;Integrated Security=true")
con1.Open()
con2 = New SqlConnection("Data Source=STLEDGSQL01;Database=MES_DEV;Integrated Security=true")
con2.Open()
con3 = New SqlConnection("Data Source=201706-SETTER1\SQLEXPRESS;Database=Edge;Integrated Security=true")
con3.Open()
con4 = New SqlConnection("Data Source=PRINTER\SQLEXPRESS;Database=Wrapper Data;Integrated Security=true")
con4.Open()
timer1 = New Timers.Timer()
timer1.Interval = 5000
AddHandler timer1.Elapsed, AddressOf OnTimedEvent
timer1.Enabled = True
FileIO.WriteLog("Service has started")
End Sub
Protected Overrides Sub OnStop()
timer1.Enabled = False
FileIO.WriteLog("Service has stopped")
con1.Close()
con2.Close()
con3.Close()
con4.Close()
End Sub
Private Sub OnTimedEvent(obj As Object, e As EventArgs)
Dim cmd1, cmd2, cmd3 As SqlCommand
'Connecting the Normac Data table
Dim da1 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, feet_produced, item_no, posted, labor_feet_produced from NOR_LABOR", con1)
Dim cb1 As SqlCommandBuilder = New SqlCommandBuilder(da1)
Dim dt1 As DataTable = New DataTable()
da1.Fill(dt1)
'Connecting the Setter_Labor table
Dim da2 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, labor_feet_produced, item_no, posted from Setter_Labor", con3)
Dim cb2 As SqlCommandBuilder = New SqlCommandBuilder(da2)
Dim dt2 As DataTable = New DataTable()
da2.Fill(dt2)
'Connecting the Wrap_Labor table
Dim da3 As SqlDataAdapter = New SqlDataAdapter("select ID, trx_date, work_order, Department, work_center, operation_no, operator, total_labor_hrs, job_start, job_end, qty_ordered, qty_produced, item_no, lot_no, default_bin, posted, wrapped, total_shift_hrs, check_emp, machine, operation_complete from wrap_labor", con4)
Dim cb3 As SqlCommandBuilder = New SqlCommandBuilder(da3)
Dim dt3 As DataTable = New DataTable()
da3.Fill(dt3)
Dim i, j, k As Integer
'Inserting into DEV_Test_Nor_Data table
For Each dr As DataRow In dt1.Rows
cmd1 = New SqlCommand("Insert into DEV_Test_Nor_Data values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "','" & dr(11) & "')", con2)
i = cmd1.ExecuteNonQuery()
Next
'Inserting into DEV_Test_Set_Lbr table
For Each dr As DataRow In dt2.Rows
cmd2 = New SqlCommand("Insert into DEV_Test_Set_Lbr values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "')", con2)
j = cmd2.ExecuteNonQuery()
Next
'Inserting into DEV_Test_Wrp_Lbr table
For Each dr As DataRow In dt3.Rows
cmd3 = New SqlCommand("Insert into DEV_Test_Wrp_Lbr values('" & dr(0) & "','" & dr(1) & "','" & dr(2) & "','" & dr(3) & "','" & dr(4) & "','" & dr(5) & "','" & dr(6) & "','" & dr(7) & "','" & dr(8) & "','" & dr(9) & "','" & dr(10) & "','" & dr(11) & "','" & dr(12) & "','" & dr(13) & "','" & dr(14) & "','" & dr(15) & "','" & dr(16) & "','" & dr(17) & "','" & dr(18) & "','" & dr(19) & "','" & dr(20) & "')", con2)
k = cmd3.ExecuteNonQuery()
Next
da1.Update(dt1)
cmd1.Dispose()
dt1.Dispose()
da1.Dispose()
da2.Update(dt2)
cmd2.Dispose()
dt2.Dispose()
da2.Dispose()
da3.Update(dt3)
cmd3.Dispose()
dt3.Dispose()
da3.Dispose()
End Sub
End Class
Reference2
Reference3
Reference4
看看这是否有帮助。可能是参数化查询是你的全部问题。
Public Class DataCollector
'Question text said one minute
Private timer1 As New Timers.Timer(60000)
Protected Overrides Sub OnStart(ByVal args() As String)
AddHandler timer1.Elapsed, AddressOf OnTimedEvent
timer1.Enabled = True
FileIO.WriteLog("Service has started")
End Sub
Protected Overrides Sub OnStop()
timer1.Enabled = False
FileIO.WriteLog("Service has stopped")
End Sub
Private Sub OnTimedEvent(obj As Object, e As EventArgs)
' DEV_Test_Nor_Data Table
ProcessOneTable("DEV_Test_Nor_Data", 12,
"Data Source=NORMAC-CTMS\SQLEXPRESS;Database=Normac Data;Integrated Security=true",
"SELECT ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, feet_produced, item_no, posted, labor_feet_produced FROM NOR_LABOR"
)
' DEV_Test_Set_Lbr Table
ProcessOneTable("DEV_Test_Set_Lbr", 11,
"Data Source=201706-SETTER1\SQLEXPRESS;Database=Edge;Integrated Security=true",
"SELECT ID, trx_date, work_order, department, work_center, operation_no, operator, total_labor_hours, labor_feet_produced, item_no, posted from Setter_Labor"
)
' DEV_Test_Wrp_Lbr Table
ProcessOneTable("DEV_Test_Wrp_Lbr", 21,
"Data Source=PRINTER\SQLEXPRESS;Database=Wrapper Data;Integrated Security=true",
"SELECT ID, trx_date, work_order, Department, work_center, operation_no, operator, total_labor_hrs, job_start, job_end, qty_ordered, qty_produced, item_no, lot_no, default_bin, posted, wrapped, total_shift_hrs, check_emp, machine, operation_complete from wrap_labor"
)
End Sub
Private EdgeConnStr As String = "Data Source=STLEDGSQL01;Database=MES_DEV;Integrated Security=true"
Private Sub ProcessOneTable(destTableName As String, ParameterCount As Integer, sourceConnectionString AS String, sourceSql As String)
Dim data As New DataTable()
Using sourceConn As New SqlConnection(sourceConnectionString), _
da As New SqlDataAdapter(sourceSql, sourceConn)
da.Fill(data)
End Using
Dim paramList As String = String.Join(",", Enumerable.Range(0, ParameterCount).Select(Function(p) $"@p{p}"))
' Assumes first parateter (@p0) is always the ID.
Dim sql As String = $"INSERT INTO {destTableName} SELECT {paramList} WHERE NOT EXISTS(SELECT ID FROM {destTableName} WHERE ID = @p0)"
Using cn As New SqlConnection(EdgeConnStr), _
cmd As New SqlCommand(sql, cn)
For i As Integer = 0 To ParameterCount - 1
cmd.Parameters.Add($"@p{i}", SqlDbType.VarChar)
Next i
cn.Open()
For Each dr As DataRow In data.Rows
For i As Integer = 0 to ParameterCount - 1
cmd.Parameters(i).Value = dr(i)
Next i
cmd.ExecuteNonQuery()
Next dr
End Using
End Sub
End Class
听起来您还需要担心 合并 数据,但无论如何都要从这里开始;它修复了原始代码中的 HUGE GAPING SECURITY ISSUE,并将代码的重要部分隔离到尽可能小的方法大小。这将使 仅重构那部分 变得更容易,同时也可以担心哪些 ID 可能已经存在......但我会让你先自己尝试一下(提示:INSERT + SELECT + WHERE NOT EXISTS()
都在同一个查询中)