SQL CLR确保执行finally块

时间:2013-01-31 01:50:43

标签: c# sql-server sqlclr clrstoredprocedure

我有一个SQL服务器CLR存储过程,用于检索大量行,然后执行一个过程并更新另一个表中的计数。

这是流程:

选择 - >过程 - >更新计数 - >将所选行标记为已处理

该过程的本质是它不应该计算两次相同的数据集。并且以GUID作为参数调用SP。

因此,我保留了当前正在处理的GUID列表(在SP中的静态列表中),并停止执行后续调用具有相同参数的SP,直到当前正在进行的处理完成。

我有一个代码在进程在finally块中完成时删除GUID但是它不是每次都有效。有些实例(比如当用户取消执行SP时)SP退出而没有调用finally块而没有从列表中删除GUID,因此后续调用会无限期地等待。

你们可以给我一个解决方案,确保无论在什么或任何其他解决方案中都能调用我的finally块,以确保在任何给定时间只有一个ID正在进行中。

以下是删除了处理位的代码示例

[Microsoft.SqlServer.Server.SqlProcedure]
public static void TransformSurvey(Guid PublicationId)
{
    AutoResetEvent autoEvent = null;
    bool existing = false;

    //check if the process is already running for the given Id
    //concurrency handler holds a dictionary of publicationIds and AutoresetEvents
    lock (ConcurrencyHandler.PublicationIds)
    {
        existing = ConcurrencyHandler.PublicationIds.TryGetValue(PublicationId, out autoEvent);
        if (!existing)
        {
            //there's no process in progress. so OK to start
            autoEvent = new AutoResetEvent(false);
            ConcurrencyHandler.PublicationIds.Add(PublicationId, autoEvent);
        }
    }
    if (existing)
    {
        //wait on the shared object
        autoEvent.WaitOne();
        lock (ConcurrencyHandler.PublicationIds)
        {
            ConcurrencyHandler.PublicationIds.Add(PublicationId, autoEvent); //add this again as the exiting thread has removed this from the list
        }
    }
    try
    {
        // ... do the processing here..........

    }
    catch (Exception ex)
    {
        //exception handling
    }
    finally
    {
        //remove the pubid          
        lock (ConcurrencyHandler.PublicationIds)
        {
            ConcurrencyHandler.PublicationIds.Remove(PublicationId);
            autoEvent.Set();
        }
    }

}

1 个答案:

答案 0 :(得分:1)

将代码包装在更高级别是一个很好的解决方案,另一个选项可能是带有IDisposable的using语句。

public class SQLCLRProcedure : IDisposable
{
     public bool Execute(Guid guid)
     {
           // Do work
     }
     public void Dispose()
     {
           // Remove GUID
           // Close Connection
     }
}

using (SQLCLRProcedure procedure = new SQLCLRProcedure())
{
  procedure.Execute(guid);
}

这在编译器中未经验证,但通常称为IDisposable Pattern。 http://msdn.microsoft.com/en-us/library/system.idisposable.aspx