Inhalt eines MemoryStream in eine Datenbank schreiben

Bella_Isy

Erfahrenes Mitglied
Hallo Leute,

ich hoffe einer von euch hat schon mal versucht einen MemoryStream in eine Datenbank gespeichert.

Vor sollte ich noch sagen, dass ich die Control ultraGrid & ultraCalendarInfo von Infragistics benutze. Infragistic stellt diese Funktion zur Verfügung. Aber ich glaube nicht, dass das bei meinem Problem von großer Bedeutung ist.

Mein Problem:
Ich habe eine Funktion die mir einem MemoryStream zurück gibt. Ein entsprechender MemoryStream muss natürlich vorher deklariert & inizialisiert sein.
Code:
System.IO.MemoryStream streamPuffer = new System.IO.MemoryStream();
ultraCalendarInfo1.Save(streamPuffer, CalendarInfoCategories.Appointments);

So weit so gut...Der Stream wurde gefüllt und ist jetzt nicht mehr "null".

Da ich ja ein MemoryStream nicht direkt speichern kann, da es sich ja nur um einem puffer im Speicher handelt hole ich mir die byte mit Hilfe folgernder Funktion.
Code:
byte[] appointments;
appointments = streamPuffer.GetBuffer();

Jetzt muss ich das byteArray nur noch in die SQL Datenbank schreiben. Aber hier liegt mein Problem! Wie soll ich den jetzt meine Insert-Anweisung gestalten? Ich habe leider keine Ahnung wie ich ein binary feld in der DB korrekt füllen kann. Ich habe mich aber ich bekomme meine Daten einfach nicht in die DB rein.

Die Daten sollen in Spalte1 in der Tabelle1 gespeichert werden. Der Datentyp von Spalte1 ist "binary(8000)". Größer kann ich diesen Sqldatentyp leider nicht gestalten. Kann mir wer helfen?

Ich hoffe es sind nun mehr keine Fragen offen!

Gruß
Isabelle
 

Norbert Eder

Erfahrenes Mitglied
Das schreibst du folgendermaßen .. eigentlich ganz einfach:

C#:
SqlCommand addEmp = new SqlCommand("INSERT INTO Tabelle1(Spalte1) VALUES (@Spalte1)",_conn);
        
addEmp.Parameters.Add("@Spalte1", SqlDbType.Image, appointments.Length).Value = appointments;
                    
_conn.Open();
addEmp.ExecuteNonQuery();
_conn.Close();
Als DatenTyp könntest du auch Image verwenden. Dann kannst da wesentlich größere Daten hineinstopfen, wenn benötigt.
 

Bella_Isy

Erfahrenes Mitglied
Also ich habe leider immer noch das Problem, dass mein Feld in der Datenbank zu klein ist. Beim Ausführen wird folgende SqlException geworfen.

"String or binary data would be truncated.The statement has been terminated."

Ich habe die Vermutung das es nicht wirklich an der größe liegt den ich habe ja nur eine byte array was eine Länge von 1024 hat. Kannst du mir vielleicht nochmal helfen und sagen was ich verkehr mache.
Code:
 string sqlInsert = "Insert Into [Xpert_Demo].[dbo].[Recall] " +
                                  "([stream]) " +
                                  "VALUES " +
                                  "(@stream)";

SqlCommand command = new SqlCommand(sqlInsert, connection);
command.Parameters.Add("@stream", SqlDbType.Image,e.Appointments.Length).Value = e.Appointments;
connection.Open();
command.ExecuteNonQuery();
connection.Close();

Ich nehme an, dass ich irgend etwas falsch bei der letzem Parameter in der Klammer gemacht habe. Spricht bei der "int size" -> "e.Appointments.Length" (Im Beispiel). Wenn ich dieses Parameter weglasse kommt aber der gleiche Fehler.

Was kann ich hier unternehmen?
 

Norbert Eder

Erfahrenes Mitglied
Hi,

natürlich habe ich jetzt die essentielle Frage vergessen: Es handelt sich hierbei schon um einen Microsoft SQL Server, oder?

Wenn ja:
Das Array hat tatsächlich nur eine Länge von 1024? Hast du dir die Length-Eigenschaft des Arrays einmal ausgeben lassen?

Du könntest auch den SqlDbType auf SqlDbType.Binary stellen, was ja eigentlich deinem Datentyp des Feldes in der Tabelle entspräche.

Wenn das nichts hilft, dann stell das Tabellen-Feld auf Image und ebenso den SqlDbType. Eventuell funktioniert es so. Ich verwende dies auf Image-Basis und da hat es ansich immer gut funktioniert.
 

Bella_Isy

Erfahrenes Mitglied
Hi,

ja, ich arbeite mit dem SQL Server 2005 und ja ich habe mir die länge ausgebenen lassen. Kann es etwas damit zutun haben das es ein Array ist?

Diese Sachen habe ich auch schon ausprobiert ich habe es mit dem datentyp "image" und mit dem Datentyp "binary" probiert. Die Datentypen in der datenbank habe ich angeglichen.

ich bin gerade dabei einem komplett anderen weg zu gehen vielleicht funktioniert es ja. Ich habe vor die byte werte (sind ja nur Zahlen) in einem string zu schreiben mit "," getrennt und dann in der Datenbank abzuspeichern. Bei laden werde ich dass den string mit der Split funktion wieder trennen und in ein Byte array schreiben mal sehn ob es klappt.
 

Norbert Eder

Erfahrenes Mitglied
So, ich hab mir schnell eine Testanwendung erstellt und eine Testdatenbank.

- SQL Server 2005 Express Edition
- Tabelle tPicture mit 2 Feldern
- ID - int
- Picture - image

Folgenden Sourcecode verwendete ich, wobei der Anfang einen Umweg darstellt, jedoch wird damit nur der MemoryStream befüllt, damit wir die gleiche Ausgangssituation haben.
C#:
SqlConnection conn = null;
try
{
    
    MemoryStream ms = new MemoryStream();
    
    byte[] pic = File.ReadAllBytes(@"D:\Fotos\Temp\IMG_0001.JPG");
    ms.Write(pic, 0, pic.Length);

    byte[] fromMS = ms.GetBuffer();

    conn = new SqlConnection(@"Data Source=INSTANCE;Initial Catalog=TestDB;Persist Security Info=True;User ID=USER;Password=PASSWORD");
    conn.Open();

    SqlCommand com = new SqlCommand("INSERT INTO tPicture (Picture) VALUES (@Picture)", conn);
    com.Parameters.Add("@Picture", SqlDbType.Image, fromMS.Length).Value = fromMS;

    com.ExecuteNonQuery();

    conn.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message + System.Environment.NewLine + ex.StackTrace);
} finally 
{
    if (conn != null)
        conn.Close();
}

Das funktioniert bei mir einwandfrei.
 

Bella_Isy

Erfahrenes Mitglied
Hallo,

alles funktioniert jetzt einwandfrei. Nur jetzt habe ich natürlich noch die Gegenfrage: Wie kann ich dieses Feld aus der Datenbank wieder in ein Byte[] speichern? Auslesen tute ich über ein SqldataReader nur der speichert ja über den Datentyp "object". Du kannst mir doch bestimmt auch sagen wie ich das machen kann.

Hier mein Code wie ich bisher auslese:
Code:
try
{
    connection.Open();
    SqlCommand com = new SqlCommand("Select Spalte1 from Tabelle1", connection);
    SqlDataReader reader = com.ExecuteReader();

    if (reader.HasRows)
    {
        while(reader.Read())
        {
            byteArray = reader[0];
        }
        reader.Close();
    }
    connection.Close();
}
catch (Exception ex)
{
     MessageBox.Show(ex.Message + System.Environment.NewLine + ex.StackTrace);
}
finally
{
    if (connection != null)
       connection.Close();
}