C# 从控制台应用程序或SQLCLR对象调用函数时,处理连接的最佳方法是使用(";Context connection=true";)
我的数据层中有以下类型的代码,可以从控制台应用程序、windows应用程序等调用,并从相应调用方的app.Config文件中读取正确的连接字符串:C# 从控制台应用程序或SQLCLR对象调用函数时,处理连接的最佳方法是使用(";Context connection=true";),c#,sql-server,sqlclr,C#,Sql Server,Sqlclr,我的数据层中有以下类型的代码,可以从控制台应用程序、windows应用程序等调用,并从相应调用方的app.Config文件中读取正确的连接字符串: public静态udsDataset GetDataset(int-datasetID) { 字符串连接字符串= ConfigurationManager.ConnectionString[“ConnectionString”].ConnectionString; 字符串sql=@“从Dataset中选择*,其中DatasetID=@DatasetI
public静态udsDataset GetDataset(int-datasetID)
{
字符串连接字符串=
ConfigurationManager.ConnectionString[“ConnectionString”].ConnectionString;
字符串sql=@“从Dataset中选择*,其中DatasetID=@DatasetID”;
使用(SqlConnection conn=newsqlconnection(connectionString))
{
//简洁的查询:
返回conn.Query(sql,new{datasetID}).First();
}
}
现在,我想从SQLCLR存储过程(在这些表所在的数据库中)调用相同的代码,您通常会在其中使用:
使用(SqlConnection=newsqlconnection(“context connection=true”))
{
connection.Open();
//等等等等等等
}
想到的最明显的方法是重载函数:
public静态udsDataset GetDataset(int-datasetID)
{
字符串连接字符串=
ConfigurationManager.ConnectionString[“ConnectionString”].ConnectionString;
使用(SqlConnection conn=newsqlconnection(connectionString))
{
返回GetDataset(datasetID,conn);
}
}
公共静态udsDataset GetDataset(int-datasetID,SqlConnection-conn)
{
//呼叫方负责关闭和处理连接
字符串sql=@“从Dataset中选择*,其中DatasetID=@DatasetID”;
返回conn.Query(sql,new{datasetID}).First();
}
因此,具有App.Config的应用程序可以调用无连接版本,SQLCLR可以调用需要SqlConnection的版本
这“似乎还可以”,但必须为每个类似的函数编写完全相同的重载样式,这会让人感觉不对劲。从表面上考虑这个问题(以及对它的评论),为什么需要:
从SQLCLR过程调用时传入现有连接的选项
??对于Open
和Dispose
,您应该像对待任何其他连接一样对待上下文连接。听起来您好像在想,当使用连接字符串“Context Connection=true;”“
”时,只需打开SqlConnection
,然后在完全打开之前不进行处理,否则您将多次打开它。我看不出有任何理由在这两种情况下有不同的行为
除此之外,如何最好地处理检测环境中的变化(在控制台应用程序和SQLCLR对象之间)?您有两种选择,两者都可能比您预期的要简单:
不更改应用程序代码,但依赖一个额外的配置文件:
您可以在C:\Program Files\Microsoft SQL Server\MSSQL{SqlVersion}.{SqlServerInstanceName}\MSSQL\Binn
文件夹中创建名为sqlservr.exe.Config
的文件(例如C:\Program Files\Microsoft SQL Server\MSSQLSERVER\MSSQL\Binn
,其中MSSQL11
中的11
用于SQL Server 2012)。该文件的格式(可能是预期的)如下所示:
SqlContext
类的属性。只需按如下方式更新原始代码:
string connectionString=“Context Connection=true;”;;//默认值=SQLCLR连接
if(!SqlContext.IsAvailable)//如果未在SQL Server中运行,请从配置文件获取
{
连接字符串=
ConfigurationManager.ConnectionString[“CoolioAppDB”]。ConnectionString;
}
顺便说一句,这种用法在链接的MSDN页面的IsAvailable
属性的“备注”部分有说明
为什么不编写一个metod GetConnection(),并在使用(sqlConnection conn=GetConnection()){}的所有地方使用它呢?GetConnection metod应该处理connectionstring,这样代码的其余部分就不必关心它了。这在理论上不会失去保证连接处理的优势吗?无论如何,当从SQLCLR过程调用时,我仍然需要传入现有连接的选项。不,该方法应该在每次调用时创建一个新连接,并且围绕它的Using()正在处理处理该处理,因此没有问题。选项#2看起来最吸引人,但要么我解释得不好,要么我误解了什么。包含GetDataset()的DLL可能正在SQL Server中运行,也可能没有运行,它可能只是部署到常规windows桌面上。我是否只需要将“使用Microsoft.SqlServer.Server”添加到该类中,然后我就可以了????因此,如果SqlContext.IsAvailable==true,则使用:connectionString=“Context Connection=true;”;如果不是,则从配置文件中读取连接字符串(这只会在不在SQL Server中运行时发生,因此我不需要在SQL Server中安装配置),假设它为true,我只需要添加“使用”,那么这个逻辑就可以被封装在一个GetConnectionString函数中,然后各个方法就不需要知道这个了,很好。@t在这里回答您的第一个评论:是的,这正是选项2的全部内容。只需使用Microsoft.SqlServer.Server添加
以便您可以测试SqlContext.IsAvailable
。无论DLL安装在何处,我发布的代码都可以工作。同样,在“备注”部分的MSDN页面中也提倡使用这个确切的用例。第二点:是的,您可以将其封装到一个通用的GetConnectionString
方法中。哦,是的,很漂亮:-)。太好了,再次感谢@srutzky,你似乎回答了我一半的问题!:)