This is a multi-part message in MIME format.
------=_NextPart_000_0128_01C3874D.EF6C4E70
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
I have a series of COM+ objects. One is called by my ASP.Net =
application and is passed the name of an action and the parameters for =
that action. That object then queries the database with the action name =
to see if it should be in a transaction, and if so, it hands off to a =
version of itself that has its TransactionOption set to Required (so I =
only run in a transaction when necessary). The called method of the =
code in both versions looks like this:
Public Function Gateway(ByVal Security As String, ByVal Action As =
String) As Object
Try
Gateway =3D CommonGateway(Security, Action)
If ContextUtil.IsInTransaction Then ContextUtil.SetComplete()
Catch
If ContextUtil.IsInTransaction Then ContextUtil.SetAbort()
Throw 'Returns error to application
End Try
End Function
So the transaction should either be committed or aborted no matter what.
The action could involve one or more calls to the database, and each =
call goes through a single COM+ object. The code for this object is =
below.
If I look at Enterprise Manager and watch the Process Info (under =
Management\Current Activity), when I call a non-transactional action =
multiple times, I notice that eventually nearly 20 processes are open to =
the database, all in "sleeping" state with 0 open transactions, command =
is "AWAITING COMMAND", application is ".Net SqlClient Data Provider", =
and subsequent calls do not raise this number. (What I find odd here is =
that one call opens two processes, and so when I make the next call, it =
doesn't immediately reuse the existing processes. Maybe that's just =
.Net's special way of preparing for load?)
If I make multiple calls to a transactional action, the number of =
connections keeps going up, with 1 open transaction each. At this =
point, I start getting errors. The error tends to vary -- sometimes =
it's a "Transaction was implicitly or explicitly committed or aborted", =
others a "timeout period elapsed prior to obtaining a connection from =
the pool", others a simple "general network error" -- but it all seems =
to be related to having so many processes open. Stopping and restarting =
SQL Server makes the error go away (until the number of processes hits =
whatever the threshhold is again).
Also of note, the COM+ objects don't shut down after the three minutes =
they're configured for.
This would all seem to indicate (to my untrained eye) that references =
are not being released somewhere, but I can't figure out how or why. At =
the very least, shouldn't the GC clean up what I'm failing to catch?
"BaseDAL" COM+ object code:
Public Enum ReturnType
NoReturn =3D 0
Scalar =3D 1
DataSet =3D 2
XML =3D 3
End Enum
=20
<System.Runtime.InteropServices.ProgId("BaseDAL.MyDB"), _
Transaction(TransactionOption.Supported), _
ObjectPoolingAttribute(Enabled:=3DTrue), _
JustInTimeActivation(True), EventTrackingEnabled(True)> _
Public Class MyDB
Inherits ServicedComponent
Private blnDebug As Boolean
=20
Private Function OpenMyDBConnection() As =
SqlClient.SqlConnection
=20
Dim oConfig As New WMS.Config 'An object to read =
the registry
OpenWarehouseDBConnection =3D New =
SqlClient.SqlConnection(oConfig.ConfigValue("MyDB", "ConnectionString"))
OpenMyDBConnection.Open()
oConfig =3D Nothing
=20
End Function
=20
Private Function BuildSPCommand(ByVal SPName As String, =
ByVal Parameters As Hashtable) As SqlClient.SqlCommand
=20
Dim oCmd As New SqlClient.SqlCommand(SPName, =
OpenMyDBConnection())
=20
Dim SqlParameter As SqlClient.SqlParameter
=20
oCmd.CommandType =3D CommandType.StoredProcedure
SqlClient.SqlCommandBuilder.DeriveParameters(oCmd)
If Not Parameters Is Nothing Then
For Each SqlParameter In oCmd.Parameters
If =
Parameters.ContainsKey(SqlParameter.ParameterName) Then
If =
IsDBNull(Parameters.Item(SqlParameter.ParameterName)) Then
SqlParameter.Value =3D =
DBNull.Value
Else
SqlParameter.Value =3D =
Parameters.Item(SqlParameter.ParameterName).ToString
End If
End If
Next
End If
BuildSPCommand =3D oCmd
oCmd =3D Nothing
=20
End Function
=20
Public Function RunSP(ByVal SP As String, ByVal ReturnType =
As BaseDAL.ReturnType, Optional ByVal Params As Hashtable =3D Nothing) =
As Object
Dim oCmd As SqlClient.SqlCommand =3D =
BuildSPCommand(SP, Params)
RunSP =3D RunAndReturn(oCmd, ReturnType)
oCmd.Dispose() : oCmd =3D Nothing
End Function
=20
Public Function RunSQL(ByVal SQL As String, ByVal =
ReturnType As BaseDAL.ReturnType) As Object
Dim oCmd As New SqlClient.SqlCommand(SQL, =
OpenWarehouseDBConnection())
RunSQL =3D RunAndReturn(oCmd, ReturnType)
oCmd.Dispose() : oCmd =3D Nothing
=20
End Function
=20
Private Function RunAndReturn(ByRef oCmd As =
SqlClient.SqlCommand, ByVal rtType As BaseDAL.ReturnType) As Object
=20
Dim oConfig As New WMS.Config, strTimeout As String
strTimeout =3D oConfig.ConfigValue("MyDB", =
"CommandTimeout")
oConfig =3D Nothing
If IsNumeric(strTimeout) Then oCmd.CommandTimeout =
=3D CInt(strTimeout)
Select Case rtType
Case ReturnType.NoReturn
RunAndReturn =3D =
oCmd.ExecuteNonQuery()
Case ReturnType.Scalar
RunAndReturn =3D oCmd.ExecuteScalar()
Case ReturnType.DataSet
Dim oDA As New =
SqlClient.SqlDataAdapter(oCmd)
Dim oDS As New Data.DataSet
oDA.Fill(oDS)
oDA.Dispose() : oDA =3D Nothing
RunAndReturn =3D oDS
Case ReturnType.XML
Dim oXMLReader As Xml.XmlReader =3D =
oCmd.ExecuteXmlReader()
Dim sbdXML As New Text.StringBuilder
If oXMLReader.Read Then
Do
=
sbdXML.Append(oXMLReader.ReadOuterXml)
Loop Until oXMLReader.EOF
End If
oXMLReader.Close() : oXMLReader =3D =
Nothing
RunAndReturn =3D sbdXML.ToString()
sbdXML =3D Nothing
End Select
End Function
=20
End Class
=20
------=_NextPart_000_0128_01C3874D.EF6C4E70
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2800.1226" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY>
<DIV><FONT face=3DArial size=3D2>I have a series of COM+ objects. =
One is=20
called by my ASP.Net application and is passed the name of an action and =
the=20
parameters for that action. That object then queries the database =
with the=20
action name to see if it should be in a transaction, and if so, it hands =
off to=20
a version of itself that has its TransactionOption set to Required (so I =
only=20
run in a transaction when necessary). The called method of the =
code in=20
both versions looks like this:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3D"Courier New"><FONT size=3D1><FONT =
color=3D#0000ff>Public=20
Function</FONT> Gateway(<FONT color=3D#0000ff>ByVal</FONT> Security =
<FONT=20
color=3D#0000ff>As String</FONT>, <FONT =
color=3D#0000ff>ByVal</FONT> Action=20
<FONT color=3D#0000ff>As String</FONT>) <FONT color=3D#0000ff>As=20
Object</FONT><BR></FONT></FONT><FONT face=3D"Courier New"><FONT =
size=3D1><FONT=20
color=3D#0000ff>Try<BR></FONT> Gateway =3D =
CommonGateway(Security,=20
Action)<BR> <FONT color=3D#0000ff>If</FONT>=20
ContextUtil.IsInTransaction <FONT color=3D#0000ff>Then</FONT>=20
ContextUtil.SetComplete()<BR></FONT></FONT><FONT face=3D"Courier =
New"><FONT=20
size=3D1><FONT color=3D#0000ff>Catch<BR></FONT> <FONT=20
color=3D#0000ff>If</FONT> ContextUtil.IsInTransaction <FONT=20
color=3D#0000ff>Then</FONT> ContextUtil.SetAbort()<BR> =
<FONT=20
color=3D#0000ff>Throw</FONT> </FONT></FONT><FONT face=3D"Courier New" =
color=3D#008000=20
size=3D1>'Returns error to application<BR></FONT><FONT face=3D"Courier =
New"=20
color=3D#0000ff size=3D1>End Try<BR>End Function</FONT></DIV>
<DIV><FONT face=3D"Courier New" size=3D1></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>So the transaction should either be =
committed or=20
aborted no matter what.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The action could involve one or more =
calls to the=20
database, and each call goes through a single COM+ object. The =
code for=20
this object is below.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>If I look at Enterprise Manager and =
watch the=20
Process Info (under Management\Current Activity), when I call a=20
non-transactional action multiple times, I notice that =
eventually nearly=20
20 processes are open to the database, all in "sleeping" state with =
0 open=20
transactions, command is "AWAITING COMMAND", application is ".Net =
SqlClient Data=20
Provider", and subsequent calls do not raise this number. (What I =
find odd=20
here is that one call opens two processes, and so when I make the next =
call, it=20
doesn't immediately reuse the existing processes. Maybe that's =
just .Net's=20
special way of preparing for load?)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>If I make multiple calls to a =
transactional action,=20
the number of connections keeps going up, with 1 open transaction =
each. At=20
this point, I start getting errors. The error tends to vary -- =
sometimes=20
it's a "Transaction was implicitly or explicitly committed or aborted", =
others a=20
"timeout period elapsed prior to obtaining a connection from the pool", =
others a=20
simple "general network error" -- but it all seems to be related to =
having so=20
many processes open. Stopping and restarting SQL Server makes the =
error go=20
away (until the number of processes hits whatever the threshhold is=20
again).</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Also of note, the COM+ objects don't =
shut down=20
after the three minutes they're configured for.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>This would all seem to indicate (to my =
untrained=20
eye) that references are not being released somewhere, but I can't =
figure out=20
how or why. At the very least, shouldn't the GC clean up what I'm =
failing=20
to catch?</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>"BaseDAL" COM+ object =
code:</FONT></DIV>
<DIV>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-spacerun: yes"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Public</SPAN> <SPAN style=3D"COLOR: =
blue">Enum</SPAN>=20
ReturnType<?xml:namespace prefix =3D o ns =3D=20
"urn:schemas-microsoft-com:office:office" =
/><o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN>NoReturn =3D=20
0<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-spacerun: =
yes"> &n=
bsp; =20
</SPAN>Scalar =3D 1<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN>DataSet =3D=20
2<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN>XML =3D=20
3<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">End</SPAN> <SPAN=20
style=3D"COLOR: blue">Enum<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Lucida =
Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =20
</SPAN><System.Runtime.InteropServices.ProgId(<SPAN=20
style=3D"COLOR: olive">"BaseDAL.MyDB"</SPAN>), =
_<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =20
</SPAN>Transaction(TransactionOption.Supported), =
_<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =20
</SPAN>ObjectPoolingAttribute(Enabled:=3D<SPAN style=3D"COLOR: =
blue">True</SPAN>),=20
_<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =20
</SPAN>JustInTimeActivation(<SPAN style=3D"COLOR: blue">True</SPAN>),=20
EventTrackingEnabled(<SPAN style=3D"COLOR: blue">True</SPAN>)>=20
_<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Public</SPAN> <SPAN style=3D"COLOR: =
blue">Class</SPAN>=20
MyDB<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Inherits</SPAN>=20
ServicedComponent<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Private</SPAN> blnDebug <SPAN style=3D"COLOR: =
blue">As</SPAN>=20
<SPAN style=3D"COLOR: blue">Boolean<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Lucida =
Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Private</SPAN> <SPAN style=3D"COLOR: =
blue">Function</SPAN>=20
OpenMyDBConnection() <SPAN style=3D"COLOR: blue">As</SPAN>=20
SqlClient.SqlConnection<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: =
2"> &nbs=
p; =20
</SPAN><SPAN style=3D"mso-tab-count: =
1"> =20
</SPAN><SPAN style=3D"COLOR: blue">Dim</SPAN> oConfig <SPAN=20
style=3D"COLOR: blue">As</SPAN> <SPAN style=3D"COLOR: blue">New</SPAN> =
WMS.Config=20
<FONT color=3D#008000>'An object to read the=20
registry<o:p></o:p></FONT></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: =
2"> &nbs=
p; =20
</SPAN><SPAN style=3D"mso-tab-count: =
1"> =20
</SPAN>OpenWarehouseDBConnection =3D <SPAN style=3D"COLOR: =
blue">New</SPAN>=20
SqlClient.SqlConnection(oConfig.ConfigValue(<SPAN=20
style=3D"COLOR: olive">"MyDB"</SPAN>, <SPAN=20
style=3D"COLOR: =
olive">"ConnectionString"</SPAN>))<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: =
2"> &nbs=
p; =20
</SPAN><SPAN style=3D"mso-tab-count: =
1"> =20
</SPAN>OpenMyDBConnection.Open()<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN>oConfig =3D=20
<SPAN style=3D"COLOR: blue">Nothing<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Lucida =
Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">End</SPAN> <SPAN=20
style=3D"COLOR: blue">Function<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: 'Lucida =
Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT =
size=3D1><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"mso-tab-count: 1"> =
</SPAN><SPAN=20
style=3D"COLOR: blue">Private</SPAN> <SPAN style=3D"COLOR: =
blue">Function</SPAN>=20
BuildSPCommand(<SPAN style=3D"COLOR: blue">ByVal</SPAN> SPName <SPAN=20
style=3D"COLOR: blue">As</SPAN> <SPAN style=3D"COLOR: =
blue">String</SPAN>, <SPAN=20
style=3D"COLOR: blue">ByVal</SPAN> Parameters <SPAN style=3D"COLOR: =
blue">As</SPAN>=20
Hashtable) <SPAN style=3D"COLOR: blue">As</SPAN>=20
SqlClient.SqlCommand<o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT-FAMILY: 'Lucida Console'"><FONT=20
size=3D1> <o:p></o:p></FONT></SPAN></P>
<P class=3DMsoNormal=20
style=3D"MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN=20
style=3D"FONT-SIZE: 8pt; FONT