从 CLR 存储过程中访问 Sql FILESTREAM

发布于 2024-08-03 01:59:54 字数 1380 浏览 15 评论 0原文

我正在尝试从 CLR 存储过程访问 Sql 文件流。我已经设置了一个非常简单的数据库,其中包含一个包含文件流列的表。我可以使用简单的控制台应用程序成功地从文件流中读取数据。以下是失败的过程的一些示例代码:

[SqlProcedure]
public static void GetDataFromFileStream(string path, out int data)
{
    using (var connection = new SqlConnection("context connection=true"))
    {
        connection.Open();

        var transaction = connection.BeginTransaction();

        var transactionContext = GetTransactionContext(connection, transaction);

        // the following line throws an exception
        var sqlFileStream = new SqlFileStream(path, transactionContext, FileAccess.Read);

        var buffer = new byte[4];
        sqlFileStream.Read(buffer, 0, 4);

        data = BitConverter.ToInt32(buffer, 0);
    }
}

private static byte[] GetTransactionContext(SqlConnection connection, SqlTransaction transaction)
{
    using (var cmd = connection.CreateCommand())
    {
        const string myGetTxContextQuery = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()";
        cmd.CommandText = myGetTxContextQuery;
        cmd.CommandTimeout = 60;
        cmd.CommandType = CommandType.Text;
        cmd.Transaction = transaction;
        return (byte[])cmd.ExecuteScalar();
    }
}

尝试构造 SqlFileStream 实例时引发异常:

发生 System.ComponentModel.Win32Exception Message="不支持该请求" 来源=“系统.数据” 错误代码=-2147467259 NativeErrorCode=50

有人知道我做错了什么吗?

I'm trying to access a Sql filestream from a CLR stored procedure. I've set up a very simple database with a single table which includes a filestream column. I can successfully read from the filestream using a simple console app. Here's some example code for the proc that fails:

[SqlProcedure]
public static void GetDataFromFileStream(string path, out int data)
{
    using (var connection = new SqlConnection("context connection=true"))
    {
        connection.Open();

        var transaction = connection.BeginTransaction();

        var transactionContext = GetTransactionContext(connection, transaction);

        // the following line throws an exception
        var sqlFileStream = new SqlFileStream(path, transactionContext, FileAccess.Read);

        var buffer = new byte[4];
        sqlFileStream.Read(buffer, 0, 4);

        data = BitConverter.ToInt32(buffer, 0);
    }
}

private static byte[] GetTransactionContext(SqlConnection connection, SqlTransaction transaction)
{
    using (var cmd = connection.CreateCommand())
    {
        const string myGetTxContextQuery = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()";
        cmd.CommandText = myGetTxContextQuery;
        cmd.CommandTimeout = 60;
        cmd.CommandType = CommandType.Text;
        cmd.Transaction = transaction;
        return (byte[])cmd.ExecuteScalar();
    }
}

An exception is thrown when trying to construct the SqlFileStream instance:

System.ComponentModel.Win32Exception occurred
Message="The request is not supported"
Source="System.Data"
ErrorCode=-2147467259
NativeErrorCode=50

Anyone know what I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

从来不烧饼 2024-08-10 01:59:54

您需要通过模拟执行查询的人来提升权限。

这是进行模拟的一个很好的示例:

http://drowningintechnicaldeb.com/blogs/shawnweisfeld/archive/2009/06/11/sql-clr-query-the-file-system-获取文件夹列表.aspx

You need to elevate permissions by impersonating the person who's executing the query.

Here is a good example of doing the impersonation:

http://drowningintechnicaldebt.com/blogs/shawnweisfeld/archive/2009/06/11/sql-clr-query-the-file-system-to-get-a-list-of-folders.aspx

蓝眼泪 2024-08-10 01:59:54

Did you use WITH PERMISSION_SET = EXTERNAL_ACCESS when creating the assembly in SQL Server? By default CREATE ASSEMBLY uses SAFE permission set, which doesn't include FileIOPermissions, required by SqlFileStream constructor.

善良天后 2024-08-10 01:59:54

我无法使用 SqlFileStream 直接从 CLR 中访问文件流(由于上面确定的问题)。我最终采用的解决方案是使用 SQL 存储过程来获取我需要的文件流数据子集。虽然这在某些场景下并不是特别有效,但对于我的应用程序来说已经足够了

    CREATE PROC ReadFromFilestream
    (
        @pfilestreamGUID    UNIQUEIDENTIFIER,
        @pOffsetIntoData    INT,
        @pLengthOfData      INT,
        @pData              VARBINARY(MAX) OUTPUT
    )
    AS
    BEGIN;
        SELECT @pData  = SUBSTRING(ValueData, @pOffsetIntoData, @pLengthOfData)
          FROM [MESL].DataStream
         WHERE DataStreamGUID = @pfilestreamGUID;
    END;

I was unable to use SqlFileStream to access the filestreams directly from within the CLR (because of the problems identified above). The solution I eventually adopted was to use a SQL stored procedure to get hold of the subset of filestream data I needed. Although this is not particularly efficient in some scenarios, it sufficed for my application

    CREATE PROC ReadFromFilestream
    (
        @pfilestreamGUID    UNIQUEIDENTIFIER,
        @pOffsetIntoData    INT,
        @pLengthOfData      INT,
        @pData              VARBINARY(MAX) OUTPUT
    )
    AS
    BEGIN;
        SELECT @pData  = SUBSTRING(ValueData, @pOffsetIntoData, @pLengthOfData)
          FROM [MESL].DataStream
         WHERE DataStreamGUID = @pfilestreamGUID;
    END;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文