在同一时间运行同一过程的多个SQL/CLR调用(如线程)

本文关键字:调用 CLR 线程 SQL 运行 同一时间 过程 | 更新日期: 2023-09-27 18:03:23

我有一个单例(因为我认为有这些可用的所有时间是有用的)来表示一些设置,这将清除旧的,并在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())
    {
        ...
    }
}

在同一时间运行同一过程的多个SQL/CLR调用(如线程)

最简单的方法是不改变现有的字典,而是创建一个新字典并自动将其写入全局变量。

为了拥有一个非只读的静态变量,你需要在SQL Server中使用不安全的权限。要注意这一点。您可以通过使用包装器类

来避免此需求。
class MutableCell<T> { public volatile T value; }
static readonly MutableCell<...> myVar = new ...();

我添加了volatile,这在这里是必需的,因为多个线程正在竞相读写该变量。

一般来说,在SQL Server内部做线程和可变状态并不是最好的主意。最好避免。您可能会引入非常困难和灾难性的错误。不过,您的场景看起来是合法的。

只需以事务方式重新加载并使用ConcurrentDictionary。

起点:http://msdn.microsoft.com/en-us/library/dd287191 (v = vs.110) . aspxhttp://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.aspxhttp://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

SQL-CLR中的线程与普通的windows代码相当不同,因为它是由称为"SQLOS"的东西处理的。线程被分配给给定任务的调度器,它们不能重新分配给不同的线程,因此您可以在那里做一些假设。也就是说

不幸的是并发字典使用了锁,所以你必须非常小心,因为它需要"不安全"的权限集。

Adam Mechanic在这方面做了一个很好的演讲:http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DBI-B404

当你运行一个进程时,它基本上是作为自己的线程分离出来的。所以两个调用它的人会发生冲突。