SQLCLR 用户定义聚合 (UDA) 中的数据访问
Data Access within SQLCLR User-Defined Aggregates (UDA)
我了解 SQLCLR 聚合在数据访问方面的局限性。话虽如此,有没有办法(解决方法)将结果存储到 table?它必须在 SQLCLR 聚合中。
在 C# 函数中准备好聚合结果后,为什么不使用 C# ADO.NET(用于数据库操作)将这些聚合存储在数据库中。这将在您的 SQL CLR 函数中,以便您从数据库中调用 SQL CLR 函数一次,它将聚合存储在一些 table 中。
为什么需要将聚合结果存储到用户定义聚合 (UDA) 中的 table 中?这几乎没有意义,因为您可以使用普通 T-SQL:
将结果存储到 table
INSERT INTO SchemaName.TableName (Col1, Col2, ...)
SELECT tab.SomeColumn, SchemaName.CustomAggregate(tab.OtherColumn)
FROM SchemaName.TableName tab
GROUP BY tab.SomeColumn;
本质上,这与存储任何内置聚合函数的结果相同,例如:SUM
、MIN
、MAX
、COUNT
、AVG
、等等
但是,如果您 确实 出于某种奇怪的原因需要这样做,只需使用外部连接(即 not Context Connection = true;
) 在 UDA 的 Terminate()
方法中。
请注意,进行此类数据访问的要求是连接不 尝试在当前事务上下文中登记(登记是默认行为)。这意味着您的连接字符串需要包含以下关键字和值:Enlist = false;
。这确实有效,因为我已经在 Terminate()
方法中成功使用了以下内容,并且在添加 Enlist=false;
之前我也得到了“在此上下文中不允许数据访问。上下文是未标记 DataAccessKind.Read 或 SystemDataAccessKind.Read 的函数或方法,是从 Table 值函数的 FillRow 方法获取数据的回调,或者是 UDT 验证方法。 ”错误。
using (SqlConnection _Connection =
new SqlConnection("Trusted_Connection=true; Enlist=false;"))
{
using (SqlCommand _Command = _Connection.CreateCommand())
{
_Command.CommandText = "SELECT TOP 1 * FROM sys.objects;";
_Connection.Open();
_Command.ExecuteNonQuery();
}
}
另请注意,建立 regular/external 连接需要将程序集标记为 EXTERNAL_ACCESS
。但是,不需要 将数据库设置为 TRUSTWORTHY ON
:您只需签署程序集,从该 DLL/程序集在 master
中创建一个非对称密钥,从该非对称密钥创建一个登录名,最后 GRANT
登录 EXTERNAL ACCESS ASSEMBLY
权限。
我了解 SQLCLR 聚合在数据访问方面的局限性。话虽如此,有没有办法(解决方法)将结果存储到 table?它必须在 SQLCLR 聚合中。
在 C# 函数中准备好聚合结果后,为什么不使用 C# ADO.NET(用于数据库操作)将这些聚合存储在数据库中。这将在您的 SQL CLR 函数中,以便您从数据库中调用 SQL CLR 函数一次,它将聚合存储在一些 table 中。
为什么需要将聚合结果存储到用户定义聚合 (UDA) 中的 table 中?这几乎没有意义,因为您可以使用普通 T-SQL:
将结果存储到 tableINSERT INTO SchemaName.TableName (Col1, Col2, ...)
SELECT tab.SomeColumn, SchemaName.CustomAggregate(tab.OtherColumn)
FROM SchemaName.TableName tab
GROUP BY tab.SomeColumn;
本质上,这与存储任何内置聚合函数的结果相同,例如:SUM
、MIN
、MAX
、COUNT
、AVG
、等等
但是,如果您 确实 出于某种奇怪的原因需要这样做,只需使用外部连接(即 not Context Connection = true;
) 在 UDA 的 Terminate()
方法中。
请注意,进行此类数据访问的要求是连接不 尝试在当前事务上下文中登记(登记是默认行为)。这意味着您的连接字符串需要包含以下关键字和值:Enlist = false;
。这确实有效,因为我已经在 Terminate()
方法中成功使用了以下内容,并且在添加 Enlist=false;
之前我也得到了“在此上下文中不允许数据访问。上下文是未标记 DataAccessKind.Read 或 SystemDataAccessKind.Read 的函数或方法,是从 Table 值函数的 FillRow 方法获取数据的回调,或者是 UDT 验证方法。 ”错误。
using (SqlConnection _Connection =
new SqlConnection("Trusted_Connection=true; Enlist=false;"))
{
using (SqlCommand _Command = _Connection.CreateCommand())
{
_Command.CommandText = "SELECT TOP 1 * FROM sys.objects;";
_Connection.Open();
_Command.ExecuteNonQuery();
}
}
另请注意,建立 regular/external 连接需要将程序集标记为 EXTERNAL_ACCESS
。但是,不需要 将数据库设置为 TRUSTWORTHY ON
:您只需签署程序集,从该 DLL/程序集在 master
中创建一个非对称密钥,从该非对称密钥创建一个登录名,最后 GRANT
登录 EXTERNAL ACCESS ASSEMBLY
权限。