这是一个Windows服务,将在大约600台机器上运行。它用于跟踪用户连接到的作业服务器(通过某种负载均衡器,而不是我的区域)。我将此信息存储在SQL表中,并希望确保没有任何SQL泄漏。
它从用户计算机(用户名/网络名称/AD名称)中获取信息,并从Load (指向一个作业服务器,所有这些服务器在检索的XML节点中都有不同的值)请求一个简单的XML,然后将这些信息发送到存储过程,该存储过程更新或将信息插入到表中,如果应用程序未打开,则不会发生这些情况。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Serialization;
using System.Data.Sql;
using System.Xml.Linq;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Data.ProviderBase;
using System.Data.Common;
using System.Data.SqlTypes;
using System.Management;
using System.Net;
using System.Threading;
namespace AppServerTracker
{
class Tracker
{
int intConnCount;
string strServer;
string strUserName;
Process[] process = Process.GetProcessesByName("MShell");
public static string strInput = "http://Website.for.load.Balancer.com";
string strErrorMSG = "No Error"; //will show that there has been no error in the table.
private static string SQLConnectionString = Properties.Resources.ConnStage;
public SqlConnection SQLConnection = new SqlConnection(SQLConnectionString);
public Tracker()
{
}
public void Main()
{
if (process.Length > 0)
{
intConnCount = process.Length;
ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_ComputerSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query);
foreach (ManagementObject mo in searcher.Get())
{
strUserName = mo["UserName"].ToString();
}
// Remove the domain part from the username
string[] usernameParts = strUserName.Split('\\');
// The username is contained in the last string portion.
strUserName = usernameParts[usernameParts.Length - 1];
string strComputerName = Environment.MachineName;
if (isValid(strInput))
{
try
{
XmlReader xmlReader = XmlReader.Create(strInput);
using (xmlReader)
{
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Text)
{
strServer = xmlReader.Value.ToString();
strServer = strServer.Replace("\r", "");
strServer = strServer.Replace("\n", "");
strServer = strServer.Replace(" ", "");
}
}
xmlReader.Close();
}
}
catch (Exception e)
{
strServer = "Error";
strErrorMSG = "Error with the xmlReader Exception as follows: " + e.ToString();
}
finally
{
}
}
else
{
strServer = "XML-Missing";
}
try
{
using (SQLConnection)
{
SQLConnection.Open();
using (SqlCommand TrackSproc = new SqlCommand("spServerTracking", SQLConnection))
{
TrackSproc.CommandType = System.Data.CommandType.StoredProcedure;
TrackSproc.Parameters.AddWithValue("@UserName", strUserName);
TrackSproc.Parameters.AddWithValue("@Server", strServer);
TrackSproc.Parameters.AddWithValue("@ConnCount", intConnCount);
TrackSproc.Parameters.AddWithValue("@MachineName", strComputerName);
TrackSproc.Parameters.AddWithValue("@Error", strErrorMSG);
TrackSproc.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
// E-mail Exception
}
finally
{
SQLConnection.Close();
}
}
}
public bool isValid(string url)
{
HttpWebRequest urlReq;
HttpWebResponse urlRes;
try
{
urlReq = (HttpWebRequest)WebRequest.Create(url);
urlReq.Method = "HEAD";
urlReq.Timeout = 100000;
urlRes = (HttpWebResponse)urlReq.GetResponse();
urlRes.Close();
return true;
}
catch (Exception ex)
{
//Url not valid
strErrorMSG = "Exception From isValid Method. Exception to follow: " + ex.ToString();
return false;
}
}
}
}
下面是这个类的全部代码。
发布于 2014-03-04 14:27:29
你的代码不对称..。
您在using块中打开您的SQLConnection
,但在最后一个块中将它关闭.总之,关闭是完全多余的。:
如果SqlConnection超出了范围,它就不会关闭。因此,必须通过调用close或Dispose显式关闭连接。关闭和处理在功能上是等价的。
您已经在try块内处理连接(作为using
的一部分),所以这一切都是毫无意义的。
SQLConnection ..。它是如何被创造出来的?你让它神奇地出现在using
的序言里.需要..。更多..。信息。
为什么要在块中注释掉旧代码。如果您不再使用sqlCommand
变量(因为它移动到外部使用块),那么请关闭它,不要注释掉该行。
如果不了解存储过程的更多功能,就很难确定是否还有其他问题,但是,您的代码看起来可能很简单(尽管当程序退出using块时,SQLConnection将被释放。这是一个不对称的情况..。连接在块启动时是打开的,我们不会返回它):
try
{
using (SQLConnection)
{
SQLConnection.Open();
using (SqlCommand TrackSproc = new SqlCommand("spServerTracking", SQLConnection))
{
TrackSproc.CommandType = System.Data.CommandType.StoredProcedure;
TrackSproc.Parameters.AddWithValue("@UserName", strUserName);
TrackSproc.Parameters.AddWithValue("@Server", strServer);
TrackSproc.Parameters.AddWithValue("@ConnCount", intConnCount);
TrackSproc.Parameters.AddWithValue("@MachineName", strComputerName);
TrackSproc.Parameters.AddWithValue("@Error", strErrorMSG);
TrackSproc.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
// E-mail Exception
}
发布于 2014-03-05 14:44:17
还不清楚您的SqlConnection是否被重用:如果客户机代码(它使用跟踪器)实例化跟踪器实例,然后多次调用Tracker.Main,那么它将被重用。
在处置完毕后,海事组织不应再使用任何物体。例如,MSDN建议类内有一个布尔值,以确保只释放一次。如果这个(合法的)模式是在SqlConnection类中实现的,那么它将不会正确地释放在释放之后重新获得的对象(如果您重用的话)。
在实践中,SqlConnection在被处理后可能被安全地重用;但是,在理论上,这是未定义的行为。用于SqlConnection.Dispose的MSDN说,
使用完组件后调用Dispose。Dispose方法使组件处于不可用的状态。调用Dispose之后,必须释放对组件的所有引用,这样垃圾收集器才能回收组件占用的内存。有关更多信息,请参见清理非托管资源和实现Dispose方法。
如果您的SQLConnection对象是局部变量,则会更安全:
using (SqlConnection sqlConnection = new SqlConnection(SQLConnectionString)) { ... }
如果希望保持SQLConnection作为跟踪器的实例成员,跟踪器实现IDisposable和从Tracker.Dispose调用SQLConnection.Dispose将是惯用的做法。
https://codereview.stackexchange.com/questions/43439
复制相似问题