I pulled a SafeFileHandle via some P/Invoke. Here’s a snippet:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeFileHandle CreateFile(
string lpFileName,
EFileAccess dwDesiredAccess,
EFileShare dwShareMode,
IntPtr lpSecurityAttributes,
ECreationDisposition dwCreationDisposition,
EFileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
Then I can grab the handle pretty easily:
SafeFileHandle fileHandle = CreateFile(path, EFileAccess.GenericRead, EFileShare.None, IntPtr.Zero,ECreationDisposition.OpenExisting, 0, IntPtr.Zero);
I have to do this because System.IO.File only takes a string path and I need to support fully qualified paths greater than the 260 character MAX_PATH.
Anyways, I have a command procedure on sql server to perform an insert. I am currently adding the byte array of the stream to a varbinary(max) column (most of my files are less than 2MB so filestream didn’t seem worth going to).
I’m currently populating the command parameter like so:
using (FileStream s = new FileStream(fileHandle, FileAccess.Read))
{
byte[] buf = new byte[s.Length];
s.Read(buf, 0, Convert.ToInt32(s.Length));
cmd.Parameters.AddWithValue("@File", buf);
}
It just seems really slow compared to the usual File.ReadAllBytes that I could use with a file path less than MAX_PATH. Is there a more optimal way to put this binary into the DB?
Pass FILE_FLAG_NO_BUFFERING flag in dwFlagsAndAttributes. Since you are reading the entire file in one go, the buffering that is built into native Windows IO is unnecessary and adds a little bit of overhead. Not sure how much it’ll save you, but sometimes every little bit helps.