SQL CLR:流表重要的函数结果

ska*_*ben 3 c# sql clr user-defined-functions

我的问题与这个问题非常相似.

但是,我正在使用SQL Server 2005 Service Pack 2(SP2)(v9.0.3042),并且在那里发布的解决方案对我不起作用.我尝试使用两个连接字符串.一个在我的代码中被注释掉了.

我意识到我可以将所有结果存储在内存中的List或ArrayList中并返回.我已经成功完成了,但这不是目标.目标是能够在结果可用时传输结果.

这可能使用我的SQL Server版本吗?

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

public static class StoredProcs
{
    [SqlFunction(
        DataAccess = DataAccessKind.Read,
        SystemDataAccess=SystemDataAccessKind.Read,
        FillRowMethodName="FillBaseline",
        TableDefinition = "[baseline_id] [int], [baseline_name] [nvarchar](256), [description] [nvarchar](max), [locked] [bit]"
        )]
    public static IEnumerable fnGetBaselineByID(SqlString projectName, SqlInt32 baselineID)
    {
        string connStr = "context connection=true";
        //string connStr = "data source=.;initial catalog=DBName;integrated security=SSPI;enlist=false";
        using (SqlConnection conn = new SqlConnection(connStr))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(String.Format(@"
                SELECT *
                FROM [DBName].[dbo].[Baseline] WITH (NOLOCK)
            "), conn))
            {
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        yield return new Baseline(reader);
                    }
                }
            }
        };
    }

    public static void FillBaseline(Object obj, out SqlInt32 id, out SqlString name, out SqlString description, out bool locked)
    {
        Baseline baseline = (Baseline)obj;
        id = baseline.mID;
        name = baseline.nName;
        description = baseline.mDescription;
        locked = baseline.mLocked;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的SQL部署脚本的一部分:

CREATE ASSEMBLY [MyService_Stored_Procs]
FROM 'C:\temp\assemblyName.dll'
WITH PERMISSION_SET = SAFE
Run Code Online (Sandbox Code Playgroud)

当我使用连接字符串"context connection = true"时,我收到此错误:

从用户定义的表值函数获取新行时发生错误:System.InvalidOperationException:在此上下文中不允许数据访问.上下文是未使用DataAccessKind.Read或SystemDataAccessKind.Read标记的函数或方法,是从表值函数的FillRow方法获取数据的回调,或者是UDT验证方法.

当我使用其他连接字符串时,我收到此错误:

从用户定义的表值函数获取新行时发生错误:System.Security.SecurityException:请求类型'System.Data.SqlClient.SqlClientPermission,System.Data,Version = 2.0.0.0,Culture = neutral,PublicKeyToken的权限= b77a5c561934e089'失败了.

ska*_*ben 5

经过进一步的研究和反复试验,我找到了解决方案.我在这里提到文章

必须使用permission_set = external_access创建程序集

这说起来容易做起来难得多,但却是一个很好的起点.只需使用该行代替permission_set = safe就会出错:

程序集'assemblyName'的CREATE ASSEMBLY失败,因为程序集'assemblyName'未授权PERMISSION_SET = EXTERNAL_ACCESS.如果满足以下任一条件,则授权程序集:数据库所有者(DBO)具有EXTERNAL ACCESS ASSEMBLY权限,并且数据库具有TRUSTWORTHY数据库属性; 或者使用具有EXTERNAL ACCESS ASSEMBLY权限的相应登录的证书或非对称密钥对程序集进行签名.

所以我要做的第一件事就是签署我的dll文件.要在Visual Studio 2010中执行此操作,请转到项目属性"签名"选项卡,然后选中"签署程序集"并为其命名.对于此示例,名称为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
Run Code Online (Sandbox Code Playgroud)

一旦如上创建登录,我现在可以使用以下方法创建程序集:

CREATE ASSEMBLY [MyDll]
FROM 'C:\Temp\MyDll.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
Run Code Online (Sandbox Code Playgroud)

现在唯一要做的就是使用正确的连接字符串.显然enlist=false与之结合使用connection=true是不可能的.这是我使用的连接字符串的示例.

string connStr = @"data source=serverName\instanceName;initial catalog=DBName;integrated security=SSPI;enlist=false";
Run Code Online (Sandbox Code Playgroud)

它的工作原理!