请查看以下代码:
Public Sub MassDelete()
Dim objCommand As SqlCommand
Dim objCon As SqlConnection
Dim objDR As SqlDataReader
Try
Dim _ConString As String = "Data Source=IANSCOMPUTER;Initial Catalog=Test5;Integrated Security=True;MultipleActiveResultSets=true"
objCon = New SqlConnection(_ConString)
Using objCon
objCommand = New SqlCommand("SELECT * FROM Person WHERE StartDate <= dateadd(-6,year," & Now & ")")
objCommand.Connection = objCon
Using objCommand
objCon.Open()
objDR = objCommand.ExecuteReader
Do While objDR.Read
'Send ID over web service
'Send email to person
'Add log entry to log file
Loop
objDR.Close()
End Using
End Using
Catch ex As Exception
Throw
Finally
End Try
我从前一个开发人员那里看到很多这样的代码,即一个循环遍历表的函数,例如:人,车辆,帐户等,并对数千或某些情况下的数百万条记录执行操作。在上述情况下,人们在开始日期后六年被删除。 while循环的每次迭代都有三个动作,即通过Web服务发送id,向人发送电子邮件并将日志条目添加到日志文件。我正在尝试重构此代码,因为我继续开发相关系统。
我认为应该有不同的电子邮件,WebService和日志类,而不是在MassDelete函数中完成所有工作;这项工作将在各类之间展开,例如电子邮件将从电子邮件类发送。为循环的每次迭代创建WebService,Email和Log对象以及使用它们的实例变量是否存在任何限制(可能有一百万条记录在Person中循环)?
答案 0 :(得分:1)
虽然对象创建便宜 - 也就是说,每个循环创建新对象不会对整体性能产生影响(取决于构造函数的工作量) - 新对象只应在它完成时才能完成在语义上正确/有意义。
在这种情况下,我主张将服务与数据(例如人员记录)分开,这只是传递给特定的服务调用。我实际上并不了解VB.NET(我使用C#),因此请根据需要调整语法。
' Note that the services are bound to some things - but NOT people
' I recommend using DI/IoC (Dependency Injection)
' Also the Logger is generally a larger application-wide service
Var mailer = New EmailService(SMTPServerString, SMTPTimeout)
Var ws = New WebService(WSEndpoint)
Var log = New LoggerService()
Var objCon = OpenConnection()
Using objCon
Var objCommand = objCon.CreateCommand(..);
Using objCommand
Var objDR = objCommand.ExecuteReader
Do While objDR.Read
' Person different per loop
Var person = New Person(objDR)
' But services are the same and are not "bound" to a person
ws.RecordDelete(person.Id)
mailer.Send(person.Email, Subject, Message)
log.Log(Log.Information, "Deleted person: " & person.Id)
Loop
End Using
End Using
当然,此代码仍然不是容错或可分发的。消息队列(例如AMPQ)可能值得研究..