0

请看下面的代码:

    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、向人员发送电子邮件以及将日志条目添加到日志文件。在继续开发相关系统时,我正在尝试重构此代码。

我认为 Email、WebService 和 Log 应该有不同的类,而不是在 MassDelete 函数中完成所有工作;工作将在各个班级之间展开,例如电子邮件将从电子邮件班级发送。为循环的每次迭代创建 WebService、Email 和 Log 对象并使用它们的实例变量(在 Person 中循环可能有一百万条记录)是否有任何限制?

4

1 回答 1

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)可能值得研究..

于 2013-03-28T22:27:48.280 回答