我有一个单例(因为我认为让它们一直可用是有用的)来表示一些设置,这将清除旧的并在clr过程调用开始时从数据库加载新设置。
但是如果像线程一样处理CLR调用,我可能会在某些时候遇到问题,确切地说清除设置,我想访问它们。
这会是一个问题吗?我可以通过一个简单的对象锁来解决这个问题吗?
修改
代码示例设置:
public class Settings
{
public static Settings Default
{
get { return _default ?? (_default = new Settings()); }
}
private static Settings _default;
private Dictionary<string, string> _settingsDict;
private Settings()
{
_settingsDict = new Dictionary<string, string>();
}
public void ReloadSettings()
{
_settingsDict.Clear();
using (var connection = new SqlConnection("context connetion=true"))
using (var command = connection.CreateCommand())
{
command.CommandText = ...
connection.Open();
// Read Settings with DataReader into _settingsDict
}
}
public string Get(string key) {
get { return _settingsDict["key"] }
}
}
步骤:
[SqlProcedure]
public static void InsertData(SqlString csv)
{
Settings.Default.ReloadSettings();
var setting = Settings.Default.Get("SETTING");
using (var connection = new SqlConnection("context connetion=true"))
using (var command = connection.CreateCommand())
{
...
}
}
答案 0 :(得分:0)
最简单的方法是不改变现有字典,而是创建一个新字典并将其原子地写入全局变量。
为了拥有非只读静态变量,您需要SQL Server中的不安全权限。要注意这一点。您可以使用包装类
来避免此要求class MutableCell<T> { public volatile T value; }
static readonly MutableCell<...> myVar = new ...();
我添加了volatile
,这是必需的,因为多个线程正在竞相读取和写入该变量。
通常,在SQL Server中进行线程化和可变状态并不是最好的想法。最好避免。您冒险引入非常困难和灾难性的错误。不过,您的方案看似合法。
答案 1 :(得分:-1)
只需以事务方式重新加载并使用ConcurrentDictionary。
起点: http://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.aspx http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
答案 2 :(得分:-1)
SQL-CLR中的线程与普通的Windows代码完全不同,因为它是由一些名为&#34; SQLOS&#34;的东西处理的。线程被分配给给定任务的调度程序,并且它们不能被重新分配到不同的线程,因此您可以在那里做出一些假设。那说
并发字典很遗憾地使用锁定,所以你必须非常小心,因为它需要&#34;不安全&#34;许可集。
Adam Mechanic对这些东西有一个非常好的演示: http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DBI-B404
当你运行proc时,它几乎被作为自己的线程分离出来。所以两个人打电话会发生冲突。