WCF中静态变量要如何使用才安全?
如 public static IList<DBIDConnStr> listDBIDConnStr = new List<DBIDConnStr>();
[最优解释]
.NET4.0里面有个BlockingCollection<T>类,可以替代List<T>,不过更倾向于使用ConcurrentDictionary<TKey,TValue>,那个可以通过唯一的“键”来达到同步目的,效果更佳。
[其他解释]
如果只是初始化一边,后面不再变的话,可以使用Static Contractor:
下面来自msdn: http://msdn.microsoft.com/en-us/library/aa645612.aspx
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
An instance of the class is created.
Any of the static members of the class are referenced.
更多讨论参考:
http://stackoverflow.com/questions/7095/is-the-c-sharp-static-constructor-thread-safe
[其他解释]
这篇文章讨论了list<t>的线程安全问题
http://www.cnblogs.com/baihmpgy/archive/2011/07/13/2105018.html
[其他解释]
你的使用场景描述下把
可以用缓存不?
[其他解释]
listDBIDConnStr这个是保存连接字符串的list,没有会加载一次,如果存在直接从这个对象中查询处理,使用basicHttpBinding,
#region DB ConnStr
/// <summary>
/// connection string list
/// </summary>
public static IList<DBIDConnStr> listDBIDConnStr = new List<DBIDConnStr>();
/// <summary>
/// load connection string
/// </summary>
private static void DefineConnStr(DBID dbID)
{
bool bConnSucceed = false;
string connStrTmp = string.Empty;
string path = AppDomain.CurrentDomain.BaseDirectory;
if (!path.EndsWith("\\"))
path += "\\";
//read xml
XmlDocument xDoc = new XmlDocument();
try
{
xDoc.Load(path + "Config.xml");
}
catch (Exception ex)
{
throw new Exception("xml读取失败" + ex.Message);
}
XmlNodeList listNodeXml = xDoc.SelectNodes("/Config/DB");
foreach (XmlNode xn in listNodeXml)
{
string strType = "";
try
{
strType = xn.Attributes["Type"].Value;
}
catch { }
if (xn.Attributes["Name"].Value.ToUpper().Equals(dbID.SubSystem.ToString().ToUpper())
&& strType.ToUpper().Equals(dbID.Type.ToString().ToUpper()))
{
string Server = xn.SelectSingleNode("/Config/DB/Server").InnerText;
string DB = xn.SelectSingleNode("/Config/DB/DataBase").InnerText;
string User = xn.SelectSingleNode("/Config/DB/User").InnerText;
string PWD = xn.SelectSingleNode("/Config/DB/PWD").InnerText;
connStrTmp = string.Format(CONNECTIONSTRINGTEMPLETE, Server, DB,
User, commonFunc.MD5Decrypt(PWD));
try
{
commonFunc.GetSqlConnection(connStrTmp);
bConnSucceed = true;
break;
}
catch { }
}
}
if (!bConnSucceed)
{
foreach (XmlNode xn in listNodeXml)
{
string Server = xn.SelectSingleNode("/Config/DB/Server").InnerText;
string DB = xn.SelectSingleNode("/Config/DB/DataBase").InnerText;
string User = xn.SelectSingleNode("/Config/DB/User").InnerText;
string PWD = xn.SelectSingleNode("/Config/DB/PWD").InnerText;
connStrTmp = string.Format(CONNECTIONSTRINGTEMPLETE, Server, DB,
User, commonFunc.MD5Decrypt(PWD));
try
{
commonFunc.GetSqlConnection(connStrTmp);
bConnSucceed = true;
break;
}
catch { }
}
}
if (!bConnSucceed)
throw new Exception("已有连接字符串无法正常连接服务器" + path);
//get db listconnstr
string Sql = @"select b.Type,a.subSystemName,b.Model,b.Server,
b.[DataBase],b.[User],b.PWD from sys_SubSystem a with(nolock)
left join sys_SubSystemDetail b with(nolock)
on a.subSystemID=b.subSystemID order by b.Type";
DataTable dt = commonFunc.GetDataTable(Sql, connStrTmp);
//init listdbidconnstr
foreach (DataRow dr in dt.Rows)
{
listDBIDConnStr.Add(new DBIDConnStr()
{
Type = commonFunc.GetEnumByStringEx<DBIDType>(dr["Type"].ToString()),
SubSystem = dr["subSystemName"].ToString(),
Model = commonFunc.GetEnumByStringEx<DBIDModel>(dr["Model"].ToString()),
Server = dr["Server"].ToString(),
DataBase = dr["DataBase"].ToString(),
User = dr["User"].ToString(),
PWD = dr["PWD"].ToString()
});
}
//update xml
xDoc.SelectSingleNode("/Config").RemoveAll();
var vQuery = listDBIDConnStr.Where(p => p.Model == DBIDModel.Security);
foreach (var vQry in vQuery)
{
XmlElement xe = xDoc.CreateElement("DB");
xe.SetAttribute("Name", vQry.SubSystem.ToString());
xe.SetAttribute("Type", vQry.Type.ToString());
XmlElement xc = xDoc.CreateElement("Server");
xc.InnerText = vQry.Server;
xe.AppendChild(xc);
xc = xDoc.CreateElement("DataBase");
xc.InnerText = vQry.DataBase;
xe.AppendChild(xc);
xc = xDoc.CreateElement("User");
xc.InnerText = vQry.User;
xe.AppendChild(xc);
xc = xDoc.CreateElement("PWD");
xc.InnerText = vQry.PWD;
xe.AppendChild(xc);
xDoc.SelectSingleNode("/Config").AppendChild(xe);
}
xDoc.Save(path + "Config.xml");
}
/// <summary>
/// Gets the conn STR.
/// </summary>
/// <param name="dbID">The db ID.</param>
/// <returns></returns>
/// <remarks></remarks>
public static string getConnStr(DBID dbID)
{
//重新启动时读
if (listDBIDConnStr.Count == 0)
{
DefineConnStr(dbID);
}
IList<DBIDConnStr> curDBIDConnstr = listDBIDConnStr.Where(p => p.Type == dbID.Type
&& p.SubSystem == dbID.SubSystem && p.Model == dbID.Model).ToList<DBIDConnStr>();
//程序运行中,新增字符串重新读,不要重启程序
if (curDBIDConnstr.Count() == 0)
{
DefineConnStr(dbID);
}
curDBIDConnstr = listDBIDConnStr.Where(p => p.Type == dbID.Type && p.SubSystem == dbID.SubSystem
&& p.Model == dbID.Model).ToList<DBIDConnStr>();
if (curDBIDConnstr.Count() == 0)
{
throw new Exception(string.Format("连接字符串未定义 {0} {1} {2}", dbID.Type, dbID.SubSystem, dbID.Model));
}
string s=string.Format(CONNECTIONSTRINGTEMPLETE, curDBIDConnstr[0].Server,
curDBIDConnstr[0].DataBase, curDBIDConnstr[0].User,
commonFunc.MD5Decrypt(curDBIDConnstr[0].PWD));
commonFunc.writeerrorlog("c:\\errorData2\\","",s);
return s;
}
#endregion
[其他解释]
非常感谢findcaiyzh,这个变量偶尔会有变化,