1


不明なファイル タイプ (jpg、doc、pdf など) をファイル システムに保存するために、ストアド プロシージャから呼び出される sql clr udf を作成しています。UFD は、呼び出し元のストアド プロシージャ (ファイル blob) から varbinary(max) を渡される SqlBytes 型のパラメーターを受け入れます。問題は、CLR UDF のコンテキストでは、以下の無効な例外エラーが返されるため、値プロパティや SqlBytes ファイル パラメータの読み取りメソッドにさえアクセスできないことです。

上記の問題を強調するために、UDF を短縮しました。どんな助けでも大歓迎です。

前もって感謝します。


エラー

このコンテキストでは、データ アクセスは許可されません。コンテキストは、DataAccessKind.Readまたはでマークされていない関数またはメソッドであるかSystemDataAccessKind.Read、テーブル値関数の FillRow メソッドからデータを取得するためのコールバックであるか、または UDT 検証メソッドです。


スタックトレース

at System.Data.SqlServer.Internal.ClrLevelContext.CheckSqlAccessReturnCode(SqlAccessApiReturnCode eRc)
   at System.Data.SqlServer.Internal.ClrLevelContext.XvarProxyRead(CClrXvarProxy* pXvarProxy, UInt64 iPosition, Byte* pbBuffer, UInt32 cbCount)
   at System.Data.SqlServer.Internal.ClrLevelContext.System.Data.SqlServer.Internal.IXvarProxyAccessor.XvarProxyRead(CClrXvarProxy* , UInt64 , Byte* , UInt32 )
   at System.Data.SqlServer.Internal.StreamOnBlobHandle.Read(Byte* pbBuffer, UInt64 offset, UInt32 count)
   at System.Data.SqlServer.Internal.XvarBlobStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.BufferedStream.Read(Byte[] array, Int32 offset, Int32 count)
   at System.Data.SqlTypes.SqlBytes.Read(Int64 offset, Byte[] buffer, Int32 offsetInBuffer, Int32 count)
   at UserDefinedFunctions.SaveFileToFS(SqlBytes file, String fileName, String fileExtension, String path)

CLRコード

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{ 

    [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.Read)]
    public static SqlString SaveFileToFS(SqlBytes file)
    {
        WindowsImpersonationContext newContext = null;
        WindowsIdentity newIdentity = SqlContext.WindowsIdentity;
        try
        {           
            if (newIdentity != null) newContext = newIdentity.Impersonate();

            byte[] buffer = new byte[8040 * 4];
            long offset = 0;
            long read = 0;

            //This file.Read will throw an error
            read = file.Read(offset, buffer, 0, buffer.Length);

            //this line will throw the same error
            buffer = (byte[])file.Value;

        catch (System.Exception ex1)
        {
            throw ex1;

        }
        finally
        {
            if (newContext != null) newContext.Undo();
        }
        return new SqlString("Success");
    }
};

したがって、このスレッドを完了するために、varbinary(max) ファイル blob、ファイル名、ファイル拡張子、および書き込み先のパスを受け入れ、定義されたファイル システムの場所に保存する CLR UDF の基本的な POC コードを次に示します (適切なファイルシステム権限があります)。それが誰かを助けることを願っています:-)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{


    [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read , SystemDataAccess = SystemDataAccessKind.Read )]
    public static SqlString SaveFileToFS(SqlBytes file, string fileName, string fileExtension, string path)
    {

        WindowsImpersonationContext newContext = null;
        WindowsIdentity newIdentity = SqlContext.WindowsIdentity;
        try
        {

            long length = file.Length ;
            byte[] buffer = file.Value;
            long offset = 0;
            long read = 0;
            int times = 0;

            if (newIdentity != null) newContext = newIdentity.Impersonate();

            FileStream fs = new FileStream(path + fileName + fileExtension, System.IO.FileMode.Create, System.IO.FileAccess.Write);
            while (length > 1000)
            {
                fs.Write(buffer, 1000 * times, 1000);          

                length -= 1000;
                times++;
            }
            fs.Write(buffer, 1000 * times, (int)length);

            fs.Close();

        }
        catch (System.Exception ex1)
        {
            throw ex1;

        }
        finally
        {
            if (newContext != null) newContext.Undo();
        }
        return new SqlString(string.Format("Saved file: {0}{1} to path: {2}", fileName, fileExtension, path));
    }



};
4

1 に答える 1

0

私が行っていたファイルシステムテストへの書き込みから残ったのは、そこにあった偽装ステートメントであることがわかりました。

以下のコード行を削除すると、すべてが期待どおりに機能します。

WindowsImpersonationContext newContext = null;

WindowsIdentity newIdentity = SqlContext.WindowsIdentity;

if (newIdentity != null) newContext = newIdentity.Impersonate(); 
于 2011-06-01T05:03:33.310 に答える