使用 ("Context Connection=true" ) 从控制台应用或 SQLCLR 对象调用函数时处理连接的最佳方法



我的数据层中有以下类型的代码,可以从控制台应用程序,windows应用程序等中调用,从相应的调用者的app . config文件中读取适当的连接字符串:

public static udsDataset GetDataset(int datasetID)         
{
   string connectionString = 
             ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
   string sql = @"select * from Dataset WHERE DatasetID=@datasetID";
   using (SqlConnection conn = new SqlConnection(connectionString))
   {
      // Dapper query:            
      return conn.Query<udsDataset>(sql, new {datasetID } ).First();
   }    
}

我现在想从SQLCLR存储过程(在存在这些表的数据库中)调用相同的代码,您通常会在其中使用上下文连接:

using(SqlConnection connection = new SqlConnection("context connection=true")) 
{
    connection.Open();
    // etc etc etc
}
最明显的方法是重载函数:
public static udsDataset GetDataset(int datasetID)
{
   string connectionString = 
       ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
   using (SqlConnection conn = new SqlConnection(connectionString))
   {
      return GetDataset(datasetID, conn);
   }
}
public static udsDataset GetDataset(int datasetID, SqlConnection conn)         
{
    // caller is responsible for closing and disposing connection
    string sql = @"select * from Dataset WHERE DatasetID=@datasetID";
    return conn.Query<udsDataset>(sql, new {datasetID } ).First();
}

所以App.Config可以调用无连接的版本,而SQLCLR可以调用需要SqlConnection的版本。

这"看起来不错",但是必须为每个类似的函数编写完全相同样式的重载,这让人感觉不对劲。

从表面上看,你为什么需要:

从SQLCLR过程调用时传入现有连接的选项

?您应该将Context Connection视为与OpenDispose有关的任何其他连接一样。听起来像你认为SqlConnection,当使用"Context Connection = true;"的连接字符串时,只需要打开一次,然后不处理,直到完全完成,而你会Open/Dispose几次否则。我看不出有什么理由在这两种情况下有不同的行为。


撇开所有这些,如何最好地处理检测环境中的变化(在控制台应用程序和SQLCLR对象之间)?你有两个选择,可能都比你想象的要简单:

  1. 不改变应用程序代码,但依赖于一个额外的配置文件:

    您可以在C:Program FilesMicrosoft SQL ServerMSSQL{SqlVersion}.{SqlServerInstanceName}MSSQLBinn文件夹中创建一个名为sqlservr.exe.Config的文件(例如C:Program FilesMicrosoft SQL ServerMSSQL11.MSSQLSERVERMSSQLBinn,其中MSSQL11中的11用于SQL Server 2012)。这个文件的格式,可能应该是预期的,如下所示:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <connectionStrings>
            <add name="CoolioAppDB" connectionString="Context Connection = true;" />
        </connectionStrings>
    </configuration>
    

    这个可能被认为是"更干净"的代码,但确实引入了一个外部依赖,DBA可能会接受,可能不喜欢但容忍,或者可能要求您的经理将您写下来;

  2. 对应用代码做一个非常小的更改,但不要依赖于额外的配置文件:

    你可以很容易地自动检测是否你当前运行在SQL server的CLR主机通过使用SqlContext类的IsAvailable属性。只需更新您的原始代码如下:

    string connectionString = "Context Connection = true;"; // default = SQLCLR connection
    if (!SqlContext.IsAvailable) // if not running within SQL Server, get from config file
    {
      connectionString = 
                ConfigurationManager.ConnectionStrings["CoolioAppDB"].ConnectionString;
    }
    

    顺便说一下,这种用法在IsAvailable属性链接的MSDN页面的"备注"部分中有说明。

最新更新