C# SQL CLR:流表值函数结果

C# SQL CLR:流表值函数结果,c#,sql,clr,user-defined-functions,C#,Sql,Clr,User Defined Functions,我的问题和我的问题非常相似 但是,我使用的是SQLServer2005ServicePack2(SP2)(v9.0.3042),发布的解决方案对我不起作用。我尝试使用两个连接字符串。一个在我的代码中被注释掉了 我意识到我可以将所有结果存储在内存中的列表或ArrayList中,然后返回。我已经成功地做到了这一点,但这不是这里的目标。目标是能够在结果可用时对其进行流式处理 使用我的SQL Server版本可以这样做吗 这是我的密码: (请注意,这些参数目前实际上没有被使用。我这样做是为了调试) 下面

我的问题和我的问题非常相似

但是,我使用的是SQLServer2005ServicePack2(SP2)(v9.0.3042),发布的解决方案对我不起作用。我尝试使用两个连接字符串。一个在我的代码中被注释掉了

我意识到我可以将所有结果存储在内存中的列表或ArrayList中,然后返回。我已经成功地做到了这一点,但这不是这里的目标。目标是能够在结果可用时对其进行流式处理

使用我的SQL Server版本可以这样做吗

这是我的密码: (请注意,这些参数目前实际上没有被使用。我这样做是为了调试)

下面是我的SQL部署脚本的一部分:

CREATE ASSEMBLY [MyService_Stored_Procs]
FROM 'C:\temp\assemblyName.dll'
WITH PERMISSION_SET = SAFE
当我使用连接字符串“context connection=true”时,出现以下错误:

从用户定义的表中获取新行时出错 有值函数: System.InvalidOperationException:中不允许数据访问 这个背景。上下文是未标记的函数或方法 对于DataAccessKind.Read或SystemDataAccessKind.Read,是一个回调 从表值函数的FillRow方法获取数据,或是 UDT验证方法

当我使用另一个连接字符串时,出现以下错误:

从用户定义的表中获取新行时出错 有值函数: System.Security.SecurityException:请求的权限 键入'System.Data.SqlClient.SqlClientPermission,System.Data, 版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089' 失败了


经过进一步的研究和反复试验,我找到了解决办法。警察说

必须使用权限\u set=external\u access创建程序集

说起来容易做起来难,但这是一个很好的起点。简单地使用该行代替permission_set=safe会出现以下错误:

为程序集“assemblyName”创建程序集失败,因为程序集 “assemblyName”未被授权进行权限设置=外部访问。 当以下任一项为真时,将授权程序集: 数据库所有者(DBO)具有外部访问程序集权限,并且 数据库在上具有可信任的数据库属性;或者组件是 使用具有 具有外部访问程序集权限的相应登录名

所以我要做的第一件事就是签署我的dll文件。要在VisualStudio2010中执行此操作,请转到“项目属性”、“签名”选项卡,选中“为程序集签名”并为其命名。在本例中,名称为MyDllKey。我选择不使用密码保护它。然后,当然,我将dll文件复制到sql server:C:\Temp

作为参考,我使用以下3个命令基于上述键创建了SQL登录:

CREATE ASYMMETRIC KEY MyDllKey FROM EXECUTABLE FILE = 'C:\Temp\MyDll.dll'
CREATE LOGIN MyDllLogin FROM ASYMMETRIC KEY MyDllKey
GRANT EXTERNAL ACCESS ASSEMBLY TO MyDllLogin
按上述方式创建登录名后,我现在可以使用以下方法创建程序集:

CREATE ASSEMBLY [MyDll]
FROM 'C:\Temp\MyDll.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
现在唯一要做的就是使用正确的连接字符串。显然,将
inclist=false
connection=true
结合使用是不可能的。下面是我使用的连接字符串的示例

string connStr = @"data source=serverName\instanceName;initial catalog=DBName;integrated security=SSPI;enlist=false";

而且它有效

最初的问题是由于在函数中使用了yield关键字,如本问题所述:

如果您避免使用yield(将结果存储在中间数组中,最后返回整个批次),那么问题就会消失

或者,您可以按照描述执行操作并避免使用上下文连接,但如果这样做,则必须按照描述将程序集标记为外部访问。我认为这是一个最好的解决办法,而不是一个解决方案,因为你输了,因为你必须跳出所有额外的障碍

在许多情况下,能够使用流行为的好处(收益率)确实超过了这一痛苦,但这两种选择仍然值得考虑

以下是Connect上的错误:

为此进行谷歌搜索:

在此上下文中不允许数据访问。要么上下文是 函数或方法未标记为DataAccessKind.Read或 SystemDataAccessKind.Read是从FillRow获取数据的回调 方法,或是UDT验证方法

引导我进入此页面,但没有找到我需要的答案。
我终于弄明白了那是什么。
在我的CLR函数中,我调用了另一个方法并传入了函数接收到的值

听起来没什么大不了的,但我所做的是对我添加的方法的输入参数使用了相同的数据类型(SqlChars、SqlBoolean、SqlInt32)

private static ArrayList FlatFile(SqlChars Delimeter, SqlChars TextQualifier)
显然,将这些数据类型用于CLR SqlFunction或SqlProcedure之外的任何对象有时都会导致这种类型的神秘错误

一旦我在新方法中删除了这些数据类型并使用了C#类型(string、bool、int),错误最终消失了

private static ArrayList FlatFile(string Delimeter, string TextQualifier)
注意:这仅在我使用模拟从另一个域获取文件时出错。
当我在本地域上传输文件时,我没有收到这个错误,这让我很反感


我希望这能在你需要的时候帮助你。我花了太多的时间来解决这个问题。

天哪,我浪费了半天时间才发现这个问题,问题一直是
yield
private static ArrayList FlatFile(string Delimeter, string TextQualifier)