Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Good job using the newer <code>If</code> rather than <code>IIf</code>. However, there are some other constructs in your code that are still throwbacks from vb6. The biggest is that the new AndAlso operator allows use of a real control/break style loop structure. There's also no need to set to Nothing after disposing an object in .Net, you can use the <code>Using</code> keyword to better handle disposing and finally blocks, and the .Net style guidelines specifically recommend against the use of hungarian notation warts like 's' or 'cls'. </p> <p>I took the liberty of restructuring your code to take advantage of that, so we'll start here. Before I move further I want to make sure this refactor hasn't introduced new bugs:</p> <h3>Update:</h3> <p>Updated my post to show all your refactored code. Note some simple name changes, as well as factoring out the connection string and changing how the OpenWiSysConn() function works.</p> <pre><code>Public Class PartsDepot Public Function ProcessPartDepotOrders() As Boolean Dim errMsg As String = "" Try Console.WriteLine(Now) ''//sendBadPOLineEmailtoDepot("test") Dim POData As New DataSet Dim dbName As String = "" Dim dbServer As String Dim partDepotDbName As String = ConfigurationManager.AppSettings("partDepotDbName") Dim partDepotDbServer As String = ConfigurationManager.AppSettings("partdepotDBserver") Dim KeyName As String = "" Dim billToCompany As String ''//, billtoCompAddr1 As String Dim dtBillTo As DataTable Dim i As Integer = 1 Dim appkeyQry = From key In ConfigurationManager.AppSettings Where key Like "CompanyDbName*" Select key ''//for each company database look for PO's For Each KeyName In appkeyQry dbName = ConfigurationManager.AppSettings(KeyName) dbServer = ConfigurationManager.AppSettings("CompanyDbServer" &amp; i) billToCompany = ConfigurationManager.AppSettings(dbName) dtBillTo = GetCustomer(billToCompany, partDepotDbName, partDepotDbServer) If dtBillTo.Rows.Count = 0 Then Throw New Exception("Customer record for company database '" &amp; dbName &amp; "' not found in the parts depot!") End If ''//billtoCompAddr1 = dtBillTo.Rows(0)("cmp_fadd1") ''//get all the unprocessed, printed PO's from the current company. POData = GetPoDataset(dbName, dbServer) If POData Is Nothing Then ''// do you really want to quit here, or do you want to move to the next key? ''// Your error handling is.. inconsistent Console.WriteLine("Error processing part depot: " &amp; errMsg) Exit Function End If Dim itemNum As String, qtyOrd As Double, requestDate As Date, promiseDate As Date, lineNum As String, itemPrice As Double Dim errNum As Integer = 0 Dim poNum As String ''//use control/break style processing loop Dim dt As DataTable = POData.Tables(0) ''// save some typing later Dim dr As DataRow = dt.Rows(0) Dim j As Integer = 0 ''// 'i' is already in use While j &lt; dt.Rows.Count ''//for each unprocessed, printed PO in the current company ''//Do setup work for next Order Number Console.WriteLine("Processing PO#: " &amp; dr("ord_no") &amp; " in " &amp; dbName) Using wsConn As Wisys.Allsystem.ConnectionInfo = OpenWiSysConn(partDepotDbName, partDepotDbServer, True), _ wsPartDepotSalesOrd As New Wisys.Oe.OrderEntryTables wsPartDepotSalesOrd.Connection(wsConn, errMsg) With wsPartDepotSalesOrd.OrderHeader .UserName = My.User.Name .Ship_to_name = If(IsDBNull(dr("cmp_name")), "", dr("cmp_name")) .Ship_to_addr_1 = If(IsDBNull(dr("cmp_fadd1")), "", dr("cmp_fadd1")) .Ship_to_addr_2 = If(IsDBNull(dr("cmp_fadd2")), "", dr("cmp_fadd2")) .Ship_to_addr_3 = If(IsDBNull(dr("cmp_fadd3")), "", dr("cmp_fadd3")) .Ship_to_addr_4 = If(IsDBNull(dr("cmp_fcity")), "", dr("cmp_fcity")) &amp; " , " &amp; _ If(IsDBNull(dr("StateCode")), "", dr("StateCode")) .Ship_to_country = If(IsDBNull(dr("cmp_fcounty")), "", dr("cmp_fcounty")) .Oe_po_no = dr("ord_no") End With ''//wsPartDepotSalesOrd.OrderHeader.Status 'readonly errNum = wsPartDepotSalesOrd.OrderHeader.Insert(TrxEnums.OeOrderTypeEnum.Order, "", billToCompany, "", dr("ord_dt"), errMsg) If errNum &lt;&gt; 0 Then Console.WriteLine("Error Creating OE header:" &amp; errMsg) Else Console.WriteLine("Created OE#" &amp; wsPartDepotSalesOrd.OrderHeader.Ord_no) End If poNum = dr("ord_no") ''//Process individual lines within one order While j &lt; dt.Rows.Count AndAlso poNum = dr("ord_no") ''//if error then skip to the next loop iteration until the next PO # and it gets inserted ok If errNum &lt;&gt; 0 Then lineNum = If(IsDBNull(dr("line_no")), Now(), dr("line_no")) itemNum = dr("item_no").ToString qtyOrd = If(IsDBNull(dr("qty_ordered")), 0, CDbl(dr("qty_ordered"))) requestDate = If(IsDBNull(dr("request_dt")), Now(), dr("request_dt")) promiseDate = If(IsDBNull(dr("promise_dt")), Now(), dr("promise_dt")) itemPrice = If(IsDBNull(dr("price")), 0, dr("price")) If itemNum.Length &gt; 0 AndAlso qtyOrd &lt;&gt; 0 Then CreateLine(wsPartDepotSalesOrd, itemNum, qtyOrd, 0, requestDate, requestDate, promiseDate, itemPrice) ''//mark as processed, even if above fails. any lines that fail will be added to SO in parts depot by hand. markPoLineAsProcessed(dbName, dbServer, poNum, lineNum) End If End If j += 1 dr = dt.Rows(j) End While ''//Do cleanup work from this order wsConn.CloseWisysConnection(TrxEnums.TransactionAction.Commit, errMsg) End Using ''// "End Using" will dispose of wsConn and wsPartDepotSalesOrd End While poNum = "" i += 1 Next KeyName Console.WriteLine("DONE") Catch ex As Exception Console.WriteLine("Exception processing part depot: " &amp; ex.Message) End Try ''// No need for finally section: Using statement ensures the objects were disposed End Function Private Function GetCustomer(ByVal CustomerNum As String, ByVal db As String, ByVal server As String) As DataTable Dim ds As New DataSet Using cn As New SqlClient.SqlConnection(GetConnectionString(db, server)), _ cmd As New SqlCommand("select cmp_name,cmp_fadd1,coalesce(debnr,crdnr) as CusNum from dbo.cicmpy where ltrim(debnr) = @cusnum or ltrim(crdnr) = @cusnum", cn), _ da As New SqlClient.SqlDataAdapter(cmd) cmd.Parameters.Add(New SqlClient.SqlParameter("@cusnum", CustomerNum)) da.Fill(ds) ''// .Fill() will open the connection if needed End Using ''// Using statement guarantees cn, cmd, and da are disposed If ds.Tables.Count &gt; 0 Then Return ds.Tables(0) End If Return Nothing End Function Private Function GetPoDataset(ByVal db As String, ByVal server As String) As DataSet Static Dim SQL As String = ConfigurationManager.AppSettings("getPoforPartsDepotSQL") Dim ds As New DataSet Using cn As New SqlClient.SqlConnection(GetConnectionString(db, server)), _ cmd As New SqlCommand(SQL, cn), _ da As New SqlClient.SqlDataAdapter(cmd) da.Fill(ds) End Using Return ds End Function Private Function GetConnectionString(ByVal db As String, ByVal server As String) Return String.Format("Persist Security Info=False;Integrated Security=true;Initial Catalog={0};server={1}", db, server) End Function Private Function OpenWiSysConn(ByVal dbName As String, ByVal dbServer As String, ByVal useTran As Boolean) As Wisys.Allsystem.ConnectionInfo Dim ci As New Wisys.Allsystem.ConnectionInfo() ci.Parameters(dbServer, dbName, "MacMSS") Dim errMsg As String = String.Empty If ci.OpenWisysConnection(useTran, errMsg) &lt;&gt; 0 Then Console.WriteLine("Error processing part depot: " &amp; errMsg) Return Nothing End If Return ci End Function Private Function CreateLine(ByVal OEObj As Wisys.Oe.OrderEntryTables, ByVal partNum As String, ByVal qtyOrdered As Double, ByVal qtyToShip As Double, ByVal RequestDate As Date, ByVal RequestShipDate As Date, ByVal PromiseDate As Date, ByVal price As Double, ByVal PONum As String) As Boolean Dim OeLine As OEORDLIN Dim RtnErrMsg As String = "" Dim RtnVal As Long Dim RtnLineNumber As Long With OEObj ''//p_lRtnVal = .OrderHeader.Read(TrxEnums.OeOrderTypeEnum.Order, RtnOrder, True, True, True, RtnRecFound, RtnErrMsg) OeLine = .OrderHeader.OrderLines.Add(TrxEnums.OrderLineType.InventoryItem, partNum.ToUpper, "", qtyOrdered, qtyToShip, price, price, RequestDate, PromiseDate, RequestShipDate, True, RtnErrMsg) RtnVal = OeLine.Insert(RtnLineNumber, RtnErrMsg) If RtnVal = 0 Then Return True Console.WriteLine("Error creating sales order line# " &amp; RtnLineNumber &amp; ": " &amp; RtnErrMsg) sendBadPOLineEmailtoDepot("Error creating sales order line for PO# " &amp; PONum &amp; " because of an error: " &amp; RtnErrMsg) Return False End With End Function Private Function markPoLineAsProcessed(ByVal DB As String, ByVal server As String, ByVal poOrdNum As String, ByVal poLineNum As String) As Boolean Static Dim SQL As String = ConfigurationManager.AppSettings("markPoLineAsSendToDepotSQL") Using cn As New SqlClient.SqlConnection(GetConnectionString(DB, server)), _ cmd As New SqlClient.SqlCommand(SQL, cn) cmd.Parameters.Add(New SqlClient.SqlParameter("@poOrdNum", poOrdNum)) cmd.Parameters.Add(New SqlClient.SqlParameter("@poLineNum", poLineNum)) cn.Open() cmd.ExecuteNonQuery() End Using Return True End Function Private Function sendBadPOLineEmailtoDepot(ByVal msgText As String) As Boolean Try If ConfigurationManager.AppSettings("EnableSentBadPOMail").ToLower &lt;&gt; "true" Then Return True Dim MailServer As String = ConfigurationManager.AppSettings("MailServer") Dim ToAddress As String = ConfigurationManager.AppSettings("BadPOMailTo") Dim FromAddress As String = ConfigurationManager.AppSettings("BadPOMailFrom") Dim mySmtpClient As New System.Net.Mail.SmtpClient(MailServer) mySmtpClient.UseDefaultCredentials = True mySmtpClient.DeliveryMethod = Net.Mail.SmtpDeliveryMethod.Network mySmtpClient.Send(FromAddress, ToAddress, msgText, msgText) Return True Catch ex As Exception Console.WriteLine("Exception sending sending bad PO line e-mail to depot: " &amp; ex.Message) Return False End Try End Function End Class </code></pre> <p>As to your specific error: it looks like you are sometimes writing through a buffer and sometimes bypassing the buffer. Alternatively, if each of the 'record' segments in the file (where a record begins with the date and ends with 'DONE') is the result of a separate instance of your app, you might also be seeing the result of several instances writing to the file at the same time. This also makes sense because the amount of traffic is one big potential difference between the server and your test environment.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload