When I try to
BULK INSERT table FROM 'c:\file.txt'
I get
Msg 4861, Level 16, State 1, Line 1
Cannot bulk load because the file "c:\file.txt" could not be opened. Operating system error code 32(The process cannot access the file because it is being used by another process.).
error since the file is a log file opened by another process.
However with C# I can open the file with System.IO.FileShare.ReadWrite as:
using (System.IO.FileStream fileStream = new System.IO.FileStream("c:\\file.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite))
{
using (System.IO.StreamReader streamReader = new System.IO.StreamReader(fileStream))
{
file = streamReader.ReadToEnd();
}
}
Is there a way to have that ReadWrite share functionality within SQL Server (bulk insert or any other)?
Thanks
Since you don't have control over the OpenFile flags that SQL Server uses behind the scenes, you may have to copy the file to a temporary file prior to doing the bulk insert.
(Reposted from my answer on DBA.SE since you deleted the question.)
BULK INSERT attempts to take a write lock on the source file to ensure that no other process is concurrently modifying the file while the read occurs. This is done to stabilize the file format, since a read could end up attempting to process a partial line being written by a concurrent writer.
Because the log file is opened for writing by another process already, this is incompatible access, and you get that error.
About the code:
FileAccess determines what you are going to do with the file.
FileShare determines what others are allowed to do with the file while you have it open.
The logging process would use FileAccess.Write or FileAccess.ReadWrite, and given that your code succeeds, probably FileShare.Read -- this would prevent others from writing to the file simultaneously, but allows them to read the contents. Your code only requests read access, and so this is compatible. If you re-run the code and request write access (FileAccess.Write) instead, the code will fail.
To use BULK INSERT to import this file, you'll have to make a copy and import that, then there won't be any file locks involved.
Related
I have a desktop application and below is the flow that is to be followed.
During app initialization, an API should be hit and an excel should downloaded to a shared location. After download is complete the app should read the excel file. This won't be a problem with a single instance of app running. But since this is a desktop app, multiple instances (on different computers) are run, app every time during initialization, downloads the file. I'm using OLE Db engine to read the file and the file is being locked and there 's error "The ole db engine cannot read the file because it is opened by another user " while another instance of the app is opened. How to prevent this?
if (response.Result.IsSuccessStatusCode)
{
using (Stream streamToWriteTo = new FileStream(pathToDownloadReport, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
response.Result.Content.CopyToAsync(streamToWriteTo).Wait();
}
}
If you want to have concurrent access to a file you need to make sure every client only takes a read-lock on the file. With OleDb you can open a connection to the file with ReadOnly access with a connection.
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\path\to\your\exelfile.xlsx;Extended Properties=\"Excel 12.0;IMEX=1;ReadOnly=true;\""
You still need to make sure no one opens the file in Excel.
Since you only can have read-only access to your file, you might as well make a local copy of the file and open that instead. That way locking won't be a problem.
I need to create a process that creates/modifies some text files in a folder. I am using below code to do that:
file = new System.IO.FileInfo(filePath);
file.Directory.Create();
System.IO.File.WriteAllText(file.FullName, "Some text...");
I have a Biztalk queue that looks into the text files in the folder every 2 minutes and picks up the files to process them. I want to lock the files when I am creating/modifying so that Biztalk wont try to process those files. How can I achieve this?
I read about Transactional NTFS in windows which will let me create Transaction context but windows documentation says this feature will deprecated and recommends not to use it.
If the file is on a local NTFS volume of CIFS share, the File Adapter will not attempt to read an open file. However,
A better pattern would be to do your file work in a temporary folder, then copy the completed files to the BizTalk folder only when they are done. That way, you don't have to worry about locking at all.
To acquire an exclusive lock you can use the file stream to do so
using (FileStream fs = new FileStream("Test.txt", FileMode.Append, FileAccess.Write, FileShare.None))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("test");
}
}
This way you are locking the file exclusively for the current file stream. Any other application or even a new instance of file stream from another thread within the same application attempts to read or write to the file will be denied by the operating system.
In most cases, write file with different extension then rename the file works fine.
I am in process of building an app which writes data continuously to a file. When I start the program the file is created and starts being written to.
However I noticed that sometimes if I have Windows Explorer open, access to the file is denied to my app, and an error is thrown.
fs = new System.IO.FileStream(location,
System.IO.FileMode.Open,
System.IO.FileAccess.Write,
System.IO.FileShare.ReadWrite);
So how do I restrict access to this file so only my app can access it, not any other programs?
You can change the last parameter from System.IO.FileShare.ReadWrite to System.IO.FileShare.None.
That locks the file in location exclusively as long as this stream is open and no other app can read, modify or delete that file except your own FileStream.
In fact this isn't only true for other apps - even your own app can't open another FileStream of that file. So keep it open as long as you need but don't forget to correctly dispose the FileStream after use.
In my case, I want to build my own "drop box" like application which I am going to use as a part of my another project.
Discription:
When a word file is opened in the "drop box" folder(inside the folder where changes to the files, file creations deletions ect.. are identified). pictures, txts, txt updates are uploaded to the server without any issue.
But when it comes to office documents. office document creation is uploaded.
Problem:
when the word file is opened, and do some update and save it. the file can not be uploaded due to permission error. even the opened file can not be copied to another place and then uploaded.
Any one faced this kind of issue, and any sugessions.
But we can manually copy and save a opened and saved(but not closed) to another location
But in the program it is not allowed.
You can create another copy of file, this is important because uploading may be slower and reading shared file may lead to conflicts for Word, so what you can do is, you can create a copy quickly on temp file and upload the temp file.
string tmp = Path.GetTempFileName();
using(Stream s = new FileStream(filePath,
FileMode.Open, FileAccess.Read,
// following option will let you open
// opened file by other process
FileShare.ReadWrite)){
using(FileStream fs = File.OpenWrite(tmp)){
// this will copy file to tmp
s.CopyTo(fs);
}
}
// upload tmp file...
your problem is similar to what we faced. In our case we are all connected to a domain directory and the problem was the antivirus installed on our server gives read/write permissions to users (executing exe, installing apps). so you specifically need to give a user the right to execute an app that wants to use another app, in this case office docs.
The problem extended to asp apps using Crystal Reports. hope it helps.
how do I use a file that is currently being used by another process?
If the file is opened with sharing permissions then you should just be able to use it. On the other hand if the process opened the file with non-sharing permissions you cannot access it until the process in question releases the file.
If you own the processes in question, you can enable read sharing by opening the file in the following way.
using (var file = new FileStream(
#"C:\path\to\file.txt",
FileMode.Open,
FileAcces.Read,
FileShare.Read) {
// ...
}
The important parameter there is the FileShare.Read