Для проекта asp.Net MVC мне нужно будет обрабатывать большие файлы (в основном 200-300Mo, иногда 1Go).
Я буду хранить их в базе данных (по причинам резервного копирования / согласованности).
Меня беспокоит проблема с производительностью, поэтому я хочу, чтобы все, что я могу, располагало массивом байтов в любом месте программы, поэтому цель состоит в том, чтобы везде работать с потоком.
У меня многоуровневое приложение, что в основном означает, что у меня есть несколько «хранилищ данных», которые отвечают за подключение и извлечение / вставку / обновление данных из базы данных.
Поскольку EF пока не поддерживает FilestreamЯ обрабатываю "Файловую часть" через простые запросы SQL.Я прочитал хорошую статью об использовании файлового потока здесь: http://blog.tallan.com/2011/08/22/using-sqlfilestream-with-c-to-access-sql-server-filestream-data/
И у меня есть несколько дополнительных вопросов, которые, я надеюсь, вы можете мне помочь / указать мне правильное направление:
- Поскольку у меня многоуровневое приложение, после того как я создал экземпляр объекта SQLFileStream, могу ли я использовать область действия SqlCommand / Sql Connection / Transaction?
- Если нет, то как мне их закрыть?
- В предыдущей ссылке есть пример, который показывает, как использовать его с ASP.Но поскольку я использую ASP.Net MVC, нет ли помощника, который может напрямую передавать файл в браузер?Потому что я нашел много примеров возврата двоичных данных в браузер, но сейчас все, что я нашел, делают что-то вроде
Stream.ToArray()
, чтобы заполнить массив байтов и вернуть его в браузер.Я обнаружил, что могу вернуть FileStreamResult
, который может принимать параметр Stream
.Это правильное направление?
(в настоящее время я не обеспокоен загрузкой больших файлов, так как они вставляются тяжелым клиентом в базу данных)
EDIT
(Извините за грязный код, здесь только 50 различных методов. Я сделал еще несколько попыток, и в настоящее время я застрял с частью "чтение", потому что разделенчасть (где мы генерируем слой и где мы его потребляем):
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);
Но я получаю исключение в rdr.GetSqlBinary(1).Value
, потому что GET_FILESTREAM_TRANSACTION_CONTEXT возвращает ноль. Я нашел здесь , что это из-запропущенная транзакция.
Я попытался с помощью «TransactionScope» + его вызов .Complete();
. Ничего не изменилось.
Я попытался выполнить НАЧАЛО СДЕЛКИ, как показано в предыдущей ссылке:
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();
Но происходит сбой при первом "ExecuteNonQuery" за исключением "A transaction that was started in a MARS batch is still active at the end of the batch. The transaction is rolled back."
Но это ПЕРВЫЙ запрос, выполненный!