2009-08-19 12 views
41

Chcę zapisać obiekt (dowolnego typu) w polu w bazie danych w SQL Server 2005. Czy to możliwe? Czy muszę przekonwertować obiekt na coś, na przykład na tablicę bajtów i odrzucić go podczas pobierania?Czy mogę zapisać "Obiekt" w bazie danych SQL Server?

+2

Można również serializowania się do XML, które byłoby łatwiej sprawdzić wewnątrz db niż dane binarne – pjp

+1

To nie jest świetny projekt DB. Czy w dowolnym momencie będziesz musiał zapytać o atrybuty obiektu? na przykład uzyskać wszystkie obiekty, w których object.Foo = 1. – Paddy

+0

Nie, nie potrzebuję znać lub zapytać o zawartość tabel przechowywanych –

Odpowiedz

27

Można użyć typu VARBINARY(MAX) pola w SQL Server, jeśli chcesz. Możesz tam przechowywać dowolny typ obiektu o rozmiarze do 2 GB.

Aby uzyskać do niego dostęp, można użyć ADO.NET - coś takiego:

object yourMysteryObject = (whatever you like it to be); 

MemoryStream memStream = new MemoryStream(); 
StreamWriter sw = new StreamWriter(memStream); 

sw.Write(yourMysteryObject); 

SqlCommand sqlCmd = new SqlCommand("INSERT INTO TableName(VarBinaryColumn) VALUES (@VarBinary)", sqlConnection); 

sqlCmd.Parameters.Add("@VarBinary", SqlDbType.VarBinary, Int32.MaxValue); 

sqlCmd.Parameters["@VarBinary"].Value = memStream.GetBuffer(); 

sqlCmd.ExecuteNonQuery(); 

Marc

+0

ale jak mogę przenieść obiekt do typu VARBINARY? –

+0

, ale jest to obraz odczytany z pliku. Co jeśli mam klasę lub obiekt utworzony w czasie wykonywania? Nic wspólnego z plikami. –

+0

każdy typ obiektu można zapisać do obiektu MemoryStream, a tym samym przypisać mu wartość parametru SqlParameter, który następnie zapisze go w bazie danych. –

10

Jak mówili inni, serializacji może być kluczem tutaj (zakładając, że nie chce użyj ORM, aby przechowywać właściwości jako kolumny w tabeli, co wydaje się dużo bardziej bezpośrednie).

Niektóre zastrzeżenia; baza danych jest:

  • przechowywanie długoterminowe
  • niezwiązane z kodem .NET

Jako takie, ty nie chcesz użyć dowolnej techniki serializacji, który jest przeznaczony dla konkretnej platformy lub wersja -konkretny. Często widzisz, że ludzie wspominają o braku zaufania, ale dotyczy to obu powyższych pułapek. Zostaniesz oszukany, jeśli kiedykolwiek zmienisz platformę lub nawet po prostu change some properties.

Potrzebujesz podejścia niezależnego od wdrożenia; najprostszym (który zachowuje również zdolność do czytania w języku ludzkim) jest xml lub json, być może przez XmlSerializer lub Json.NET (przechowywany w [n]varchar(max)). Jeśli nie dbasz o czytelność czytelną dla człowieka, "bufory protokołów" (szybkie/binarne) dobrze by działały (przechowywane w varbinary(max)) i są available for most platforms (w tym C#/.NET/etc).

17

Chciałbym użyć JSON, aby przekonwertować obiekt na ciąg i zapisać go w polu VARCHAR lub TEXT. Nie tylko dane są przechowywane w formacie czytelnym dla człowieka, ale można je również odczytać z różnych języków, ponieważ prawie każdy język głównego nurtu ma dostępny parser JSON.

Opublikowany przeze mnie link zawiera linki do kilku bibliotek w wielu językach (w tym w języku C#), kilka razy używałam this one.

+0

Niestety masz teraz martwe linki do tej strony. http://jayrock.berlios.de/ –

+0

Dzięki, link zaktualizowany. – Badaro

10

Oto przykład, jeśli używasz Entity Framework (EF):

  using (DbContext db = new DbContext()) 
      { 
       // The object that you want to serialize. In this case it is just an empty instance 
       YourObject objectToSerialize = new YourObject(); 
       IFormatter formatter = new BinaryFormatter(); 
       using (MemoryStream stream = new MemoryStream()) 
       { 
        formatter.Serialize(stream, objectToSerialize); 

        // EF model. In one of its properties you store the serialized object 
        YourModel modelObject = new YourModel(); 

        // In your model 'SerializedObject' should be of type byte[]. In the database it should be of type varbinary(MAX) 
        modelObject.SerializedObject = stream.ToArray(); 
        db.YourModel.Add(modelObject); 
        db.SaveChanges(); 
       } 
      } 

I to jest jak de-serializacji obiektu:

// De-serialize 
      IFormatter formatter = new BinaryFormatter(); 
      Stream stream = new MemoryStream(serializedObject); 
      YourObject deserializedYourObject = (YourObject)formatter.Deserialize(stream); 
      stream.Close(); 
+0

Jak odrzucić to z powrotem do obiektu, który właśnie uratowaliśmy ... wiedząc, co pierwotnie było oczywiste. – ppumkin

+1

@ppumpkin. Zaktualizowałem swoją odpowiedź z informacją, jak odserializować obiekt. Szczęśliwe kodowanie :) –

+0

Klasyfikująca się klasa musi być oznaczona atrybutem Serializable. – Elton

Powiązane problemy