views:

232

answers:

2

I'm trying to use the

OpenSqlFilestream

Instruction but my code did not recognise it

What dll i have to load in order to use it?

+1  A: 

Do you do all the necessary steps before opening the file stream? Grabbing the context inside a transaction??

Check out this article here for a detailed discussion as to how to do it. Here's another blog post with a VB.NET sample code snippet.


Update: Lefteris, your code snippet is very very hard to read and understand, I did my best, but I'm really not sure. What I'm thinking is that you close the transaction too quickly. You seem to create a connection and a transaction to get the GET_FILESTREAM_TRANSACTION_CONTEXT, but then you close that again before you actually write out your bytes. I think the transaction should span all operations - it should start before you get the transaction context, and it should stay alive for the whole write operation, and only be committed once the whole write operation is done.

I tried to come up with a simpler code snippet to show you - it's in C#, since I couldn't convert it back to VB.NET:

public static void WriteFileStream(byte[] imSource, int imSize)
{ 
   // use your own SQL insert command here instead
   const string InsertCmd = "INSERT INTO PhotoAlbum(PhotoId, Description)" +
          " VALUES(@PhotoId, @Description)";

   using (SqlConnection conn = new SqlConnection(ConnStr))
   {
       conn.Open();

       // create transaction here and let it stay alive!
       using (SqlTransaction txn = conn.BeginTransaction())
       {
            using (SqlCommand cmd = new SqlCommand(InsertCmd, conn, txn))
            {
               cmd.Parameters.Add("@PhotoId", SqlDbType.Int).Value = photoId;
               cmd.Parameters.Add("@Description", SqlDbType.VarChar).Value = desc;
               cmd.ExecuteNonQuery();
            }

            SafeFileHandle handle = GetOutputFileHandle(photoId, txn);

            MemoryStream inputStream = new MemoryStream(imSource);

            using (FileStream dest = new FileStream(handle, FileAccess.Write))
            {
               byte[] buffer = new byte[BlockSize];
               int bytesRead;

               while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
               {
                   dest.Write(buffer, 0, bytesRead);
               }
               dest.Close();
            }

            inputStream.Close();

            // commit transaction here, after all is done                
            txn.Commit();
        }
        conn.Close();
    }
}

This is adapted from the blog post SQL Server 2008 FILESTREAM Part 3: OpenSqlFileStream API - check that out by all means!

marc_s
Well I have already done all the instractions i see in the links abovebut steel have returned error 'Access is Denied'Now lets look at my next comment
Lefteris Gkinis
I have change my code in order; before the opening of the filestream file to close all the open connections (that in my server and the other in my database)Also i close the transaction i'm changing the logon account in my PC and then i reopen all the above connections The new account is a windows sytem account which is registered from the Active directory of the server machineAnd now i'm taking a new message'The Function has wrong parameters' and now i'm stack again
Lefteris Gkinis
It's hard to figure out what goes wrong - unless you start posting some code in your original question, so that we can see what might be wrong.
marc_s
i will give you my code in a separate windowPlease look at it
Lefteris Gkinis
A: 

Dear marc_s look at my code

Public Sub WriteFileStream(ByVal imSource As Byte(), ByVal imSize As Integer, ByVal imTy As Type, ByVal sender As Object, ByVal e As EventArgs)
    Dim subProvider As String = Nothing
    Dim subDataSource As Object = Nothing
    Dim subUid As String = Nothing
    Dim subPwd As String = Nothing
    Dim subDataBase As String = Nothing
    Dim subPSI As Boolean = Nothing
    Dim ParamXML() As String = Nothing
    Dim TypeOfServer As String = "Remote"
    Dim imParam(3) As String
    Dim imTable(1) As String
    Dim RemoteSQLcmd As SqlCommand = New SqlCommand
    Dim tokenReader As SqlDataReader
    '-------------------------------------------------'

    Dim AbsRecord As Int64 = 0
    Dim VarString(10) As String
    Dim VarInt(10) As Integer
    '-------------------------------------------------'
    ParamXML = Split(loadXmlFile(TypeOfServer, sender, e), "|")
    subUid = ParamXML(3)
    subProvider = ParamXML(0)
    subDataSource = ParamXML(1)
    subDataBase = ParamXML(2)
    subPwd = ParamXML(4)
    subPSI = ParamXML(5)

    Dim SchemaID As String = Convert.ToInt16(ParamXML(8))
    Dim SchemaName As String = Nothing
    If SchemaID = 1 Then
        SchemaName = subUid
    ElseIf SchemaID = 2 Then
        SchemaName = "dbo"
    ElseIf SchemaID = 0 Then
        SchemaName = "dbo"
    End If
    '-------------------------------------------------'
    imTable(0) = "tPDetails"
    imTable(1) = "tPImages"
    Try
        imParam(0) = Me.TextBox1.Text.Trim.ToString     'Name'
        imParam(1) = Me.TextBox2.Text.Trim.ToString     'Code'
        imParam(2) = Me.TextBox3.Text.Trim.ToString     'Price'
        imParam(3) = Me.TextBox4.Text.Trim.ToString     'Comments'
        '========================================================'
    If RemoteSQLConn.State = ConnectionState.Open Then RemoteSQLConn.Close()
    SQL_Connection(TypeOfServer, TypeOfServer & "Conn.xml", sender, e)
    RemoteSQLConn.open()

        '----------------------'
        Dim imHolder As Image = Image.FromStream(imStream)
        Dim imHeight As Integer = imHolder.Height
        Dim imWidth As Integer = imHolder.Width
        Dim imLength As Integer = imHolder.PropertyItems.Length
        Dim imType As Type = imTy
        '----------------------'
        Dim FirstColumnNames As String = _
                                imTable(0) & "_Code, " & _
                                imTable(0) & "_Price, " & _
                                imTable(0) & "_Title, " & _
                                imTable(0) & "_Type, " & _
                                imTable(0) & "_Height, " & _
                                imTable(0) & "_Width, " & _
                                imTable(0) & "_Stock, " & _
                                imTable(0) & "_Comments "
        Dim FirstFieldsValues As String = "'" & imParam(1) & "', '" & _
                                imParam(2) & "', '" & _
                                imParam(0) & "', '" & _
                                imType.ToString & "', '" & _
                                imHeight & "', '" & _
                                imWidth & "', '" & _
                                "0', '" & _
                                imParam(3) & "' "
'--------------------------------------------'
           RemoteSQLcmd = New SqlCommand("INSERT INTO " & _
    SchemaName & "." & imTable(0) & " (" & FirstColumnNames & ")                     VALUES (" & FirstFieldsValues & ") ", RemoteSQLConn)
            RemoteSQLcmd.ExecuteNonQuery()
            '--------------------------------------------------'
    RemoteSQLcmd = New SqlCommand("SELECT * FROM " & SchemaName & "." & imTable(0) & _
    " WHERE " & imTable(0) & "_Code = " & "'" & imParam(1) & "'", RemoteSQLConn)
            AbsRecord = RemoteSQLcmd.ExecuteScalar
            '--------------------------------------------------'
      RemoteSQLcmd = New SqlCommand("INSERT INTO " & SchemaName & "." & imTable(1) & " VALUES (newid(), " & AbsRecord & ", CAST('' as varbinary(max)))", RemoteSQLConn)

            RemoteSQLcmd.ExecuteNonQuery()
            '--------------------------------------------------'
    RemoteSQLcmd = New SqlCommand("SELECT " & imTable(1) & "_Image.PathName() FROM " & _
SchemaName & "." & imTable(1) & " WHERE " & imTable(1) & "_" & imTable(0) & "_ID = " & AbsRecord, RemoteSQLConn)
            Dim filePathName As String = Nothing
            Dim pathObj As Object = RemoteSQLcmd.ExecuteScalar()
'--------------------------------------------------   Path Name  '
            If Not pathObj.Equals(DBNull.Value) Then
                filePathName = DirectCast(pathObj, String)
            Else
    Throw New System.Exception("Image.PathName() failed to read the path name for the Image column.")
            End If
    '--------------------------   GET_FILESTREAM_TRANSACTION_CONTEXT()'
            Dim RemoteSQLtx As SqlTransaction = RemoteSQLConn.BeginTransaction("MainTranaction")
            RemoteSQLcmd.Transaction = RemoteSQLtx
    RemoteSQLcmd = New SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()", RemoteSQLConn, RemoteSQLtx)
            Dim tokenObject As Object = RemoteSQLcmd.ExecuteScalar()
        '--------------------------------------   File Token '
            tokenReader = RemoteSQLcmd.ExecuteReader(CommandBehavior.SingleRow)
            tokenReader.Read()
            Dim txContext As SqlBinary = DirectCast(tokenObject, Byte())
            tokenReader.Close()
            '-----------------------------------------------'
            Try
                '--------------------  Closing all connections'
       If RemoteSQLConn.State = ConnectionState.Open Then RemoteSQLConn.Close()
       If RemoteSQLcmd.Connection.State = ConnectionState.Open Then RemoteSQLcmd.Connection.Close()
                If RemoteConnInfo.State = ConnectionState.Open Then RemoteConnInfo.Close()
                RemoteSQLtx.Dispose() '.Connection.State = ConnectionState.Open Then RemoteSQLtx.Connection.Close()
       '--------------------  Open connections for Indegrated Security''
                ChangeLoginPerson("PRINCIDEVEL\Administrator")
                RemoteConnInfo.ConnectionString = "Provider=" & subProvider & "; Data Source=" & subDataSource & _
                "; Database=" & subDataBase & "; Integrated Security=" & "SSPI" & "; Persist Security Info=" & subPSI
                RemoteSQLcmd.Connection.Open()
                RemoteSQLConn = New SqlConnection("Server=" & subDataSource & "; Integrated Security=TRUE" & "; database=" & subDataBase)
                RemoteSQLConn.Open()
                RemoteSQLtx = RemoteSQLConn.BeginTransaction("MainTranaction")
                RemoteSQLcmd.Transaction = RemoteSQLtx
                '-------------------------  Write in to file stream   ---------------'
                Dim imImage As Byte() = New Byte(imStream.Length) {}
                Dim bytesRead As Integer = imStream.Read(imImage, 0, imStream.Length)
                Dim sqlFile As New SqlFileStream(filePathName, txContext, FileAccess.ReadWrite, FileOptions.WriteThrough, 0)
                Dim numBytes As Integer = 0
                Dim unicode As Encoding = Encoding.GetEncoding(0)
                While bytesRead > 0
                    sqlFile.Write(imImage, 0, bytesRead)
                    bytesRead = imStream.Read(imImage, 0, imSize)
                End While
                RemoteSQLtx.Commit()
                RemoteSQLcmd.Transaction.Commit()
                sqlFile.Close()
            Catch FsEx As Exception
                MessageBox.Show(FsEx.Message, "Write in SQL File Stream ", MessageBoxButtons.OK, MessageBoxIcon.Stop)
            Finally
            End Try
            '--------------------------------------------------'
        Catch ex As Exception
MessageBox.Show(ex.Message, "WriteFileStream ", MessageBoxButtons.OK, MessageBoxIcon.Stop)
            Finalize()
        Finally
            RemoteSQLConn.Close()
            imStream.Close()
        End Try


    End Sub
Lefteris Gkinis
Now with changes my error has new message---'Wrong parameters in the function'---.and now i'm trying to see what is going on.But in fact when i will turn my code to my ISP in order to do my job then i believe i will have the real security problems .For the moment i'm working on my Server
Lefteris Gkinis
Yes marc_s i see what you mean and also i have seen this code snippet but i didn't use it because i have another idea of writing an image to sql server.---But now i will try your snippet since i', in the end of this try'--It is very hard to read it because inside of this SUB take place more actions than the image writing.--Additionally i'm updating another table as well on which i kepp some other details of the image.--the transaction is opened just before of GET_FILESTREAM_TRANSACTION_CONTEXT and it is closed after that since i have the FilePath and the bytes
Lefteris Gkinis
When i'm executing the instruction FileStream write i have all the parameters i need for it.--I will your code and i'll be back to tell inform youThanks for all of your try, thanks alot
Lefteris Gkinis