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
(汚いコードについて申し訳ありませんが、それだけです 私はいくつかの試みをしましたが、私は現在、レイヤーを生成して消費する場所が分かれているため、 "読み取り"部分に悩まされています:
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);
しかし、GET_FILESTREAM_TRANSACTION_CONTEXTがnullを返すため、rdr.GetSqlBinary(1).Value
に例外が発生します。私はhereが見つからないことが原因です。
私は "TransactionScope" +その.Complete();
コールを試しました。何も変わらない。
私は、以前のリンクで示したように、BEGIN TRANSACTIONを実行しようとしました:
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."
しかし、それは実行された最初のクエリです!
あなたはファイルを扱っているので、これはファイルシステムに適したタスクだと思います。サイト/データベースがWindowsマシンに配備されていると仮定すると、見るべき代替案はTransactional NTFSとなる可能性があります。 DTMを使用して他のトランザクションと統合する必要があります。確かにそこにはいくつかの問題がある(例えば、ファイル共有のサポートが悪い)。 +1はバイト[]を使用していないためです: –