2017-01-10 6 views
1

私は、次の形式で、SQL Serverのテーブルにファイルを格納しています:SQL ServerとC# - アップロードするvarbinary(max)ファイルが既にテーブルに存在するかどうかを確認する方法はありますか

FILEID - int型(自動インクリメント)、 ファイル名 - VARBINARY(MAX)、 FILEDATA - varbinary型(MAX)を。

私は何をしたいのです - パラメータとして新しいファイル名&、FILEDATAをアップロードして、最初のfileIDを返すところそれほどのようなファイル名&ファイルデータが一致し、:

SqlCommand cmd = new SqlCommand("SELECT TOP 1 FileID FROM Attachments WHERE FileName = @FileName AND FileData = @FileData", Program.connection); 
cmd.Parameters.AddWithValue("@FileName", Path.GetFileName(MyFile)); 
cmd.Parameters.Add("@FileData", SqlDbType.VarBinary).Value = File.ReadAllBytes(MyFile); 
int result = (int)cmd.ExecuteScalar(); 

しかし、私は何をすべきかに関係なく、 、最後の行で実際にクエリを実行するときに関数は(例外なく)終了するだけです。私は間違って何をしていますか?

各ファイルのデータを取得したくない場合は、可能であればC#で比較してください。&

+0

チェックサムまたはハッシュのいくつかの形式を考慮したので、実行する必要がある完全な比較の数を大幅に減らすことができます。 –

+0

サイドノート:ファイルの_contents_を比較しないでください。代わりに、ファイルハッシュを計算し、内容と一緒に格納します。次に、アップロード時に、ハッシュを計算し、データベースに格納されているものと比較します。ハッシュは非常に短いので、はるかに効率的です。 – Evk

+0

"可能であれば、各ファイルのデータを取得せずにC#で比較したいと思っています。"ファイル全体を読み込んでSQL Serverにアップロードし、比較を行うことを求めることはほとんど効率的ではありません。他の人が言ったように、衝突の可能性を十分に小さくして、可能性を考慮する必要がないような(良い、暗号指向の)チェックサムを採用します。 –

答えて

2

他の人が既にコメントに書いているように: 最初に、2つの列をさらに保持するようにテーブルを拡張します。 1つはコンテンツのハッシュ用で、もう1つはファイル長用です。 ファイルの内容をハッシュして、ユーザーがファイルをアップロードして長さを取得したときにハッシュできます。次に、同じ長さと同じハッシュ(同じ名前のファイルを別のファイルと見なす場合は同じ名前)を含む行を検索するために、SQL Serverを照会します。 ヒットした場合は、ファイルをSQL Serverに転送しません。ヒットしなかった場合は、新しいレコードを作成します。

希望に役立ちます。

+0

ハッシュ列にはどのようなデータ型を使用する必要がありますか? where句がvarbinary列にあるとき、私は問題が発生しているようです。 –

+0

たとえば、ハッシュをbase64に変換し、等価クエリをサポートするvarcharフィールドに格納することができます。 –

関連する問題