W przypadku projektu asp.Net MVC będę musiał obsługiwać duże pliki (głównie 200-300Mo, czasami 1Go).Aplikacja warstwowa: Przechowuj plik w strumieniu filestream w bazie danych
Będę przechowywać je w bazie danych (z powodów związanych z kopiami bezpieczeństwa/spójności).
Jestem zaniepokojony problemem z wydajnością, więc chcę uniknąć wszystkiego, co możliwe, aby mieć cały szereg bajtów w dowolnym miejscu programu, więc celem jest praca ze strumieniem w dowolnym miejscu.
Mam warstwę aplikacji, co oznacza, że mam kilka "DataStore", które są odpowiedzialne za łączenie i pobieranie/wstawianie/aktualizowanie danych z bazy danych.
Ponieważ EF nie obsługuje teraz Filestream, zajmuję się "Częścią pliku" za pomocą prostych zapytań Sql. Czytałem artykuł na dobre wykorzystanie FILESTREAM tutaj: http://blog.tallan.com/2011/08/22/using-sqlfilestream-with-c-to-access-sql-server-filestream-data/
i mam kilka dodatkowych pytań, które mam nadzieję, że może mi pomóc/wskaż mnie dobrym kierunku:
- odkąd aplikacja warstwowa po utworzeniu obiektu SQLFileStream, czy mogę zlikwidować zasięg połączenia SqlCommand/Sql/Transaction?
- Jeśli nie, to jak mam je zamknąć?
- W poprzednim linku znajduje się przykład pokazujący, jak używać go w ASP. Ale skoro używam ASP.Net MVC, czy nie ma pomocnika, który mógłby bezpośrednio przesłać plik do przeglądarki? Ponieważ znalazłem wiele przykładów danych binarnych zwracanych do przeglądarki, ale na razie wszystkie znalezione przykłady sprawiają, że w zasadzie wypełniają tablicę bajtów i zwracają ją do przeglądarki. Zauważyłem, że mogę zwrócić wartość
FileStreamResult
, która może przyjąć parametr o wartościStream
. Czy to właściwy kierunek?
(nie jestem obecnie objęty przesyłania dużych plików, ponieważ są one wstawiane przez ciężki klienta w bazie danych)
EDIT
(przepraszam za brudną kodu, to tylko nie mam tutaj 50 różnych metod. Zrobiłem jeszcze kilka prób i obecnie utknąłem w części "przeczytanej", ponieważ oddzielona część (gdzie generujemy warstwę i gdzie ją konsumujemy):
SqlConnection conn = GetConnection();
conn.Open();
SqlCommand cmd = new SqlCommand(_selectMetaDataRequest, conn);
cmd.Parameters.Add(_idFile, SqlDbType.Int).Value = idFile;
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string serverPath = rdr.GetSqlString(0).Value;
byte[] serverTxn = rdr.GetSqlBinary(1).Value;
rdr.Close();
return new SqlFileStream(serverPath, serverTxn, FileAccess.Read);
Ale otrzymuję wyjątek pod adresem rdr.GetSqlBinary(1).Value
, ponieważ funkcja GET_FILESTREAM_TRANSACTION_CONTEXT zwraca wartość null. Znalazłem here, że jest to spowodowane brakującą transakcją.
Próbowałem z połączeniem "TransactionScope" + jego .Complete();
. Nic nie zmienia.
Próbowałem zrobić transakcję BEGIN jak pokazał w poprzednim linku:
SqlConnection connection = GetConnection(); connection.Open(); SqlCommand cmd = new SqlCommand();
cmd.CommandText = "BEGIN TRANSACTION";
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.ExecuteNonQuery();
cmd = new SqlCommand(_selectMetaDataRequest, connection);
cmd.Parameters.Add(_idFile, SqlDbType.Int).Value = idFile;
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string serverPath = rdr.GetSqlString(0).Value;
byte[] serverTxn = rdr.GetSqlBinary(1).Value;
rdr.Close();
SqlFileStream sqlFileStream = new SqlFileStream(serverPath, serverTxn, FileAccess.Read);
cmd = new SqlCommand(); cmd.CommandText = "COMMIT TRANSACTION"; cmd.CommandType = CommandType.Text; cmd.Connection = connection; cmd.ExecuteNonQuery();
Ale to zawiesza się na pierwszym "ExecuteNonQuery" z wyjątek "A transaction that was started in a MARS batch is still active at the end of the batch. The transaction is rolled back."
Ale to PIERWSZE zapytanie zostało wykonane!
Powiedziałbym, że jest to zadanie bardziej odpowiednie dla systemów plików, ponieważ mamy do czynienia z plikami. Zakładając, że lokacja/baza danych jest wdrażana na komputerze z systemem Windows, jedną z opcji alternatywnych może być Transactional NTFS. Powinien nawet zintegrować się z innymi transakcjami za pomocą DTM. Trzeba przyznać, że są tam pewne błędy (np. Złe wsparcie dla plików). +1 dla nie używania bajtu [] :) –