How to Connect to a Remote Database - c#

I am having some trouble connecting to an Access database which sits on a remote computer:
The Microsoft Access database engine cannot open or write to the file '\\ACCESSSERVER-PC\Warehouse Manager\Error Logging\Error Logging.accdb'. It is already opened exclusively by another user, or you need permission to view and write its data.
The database is not open for editing by anyone else and I should be able to connect to it.
I am using this connection string:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\ACCESSSERVER-PC\Warehouse Manager\Error Logging\Error Logging.accdb;Persist Security Info=False;
And the error occurs when calling connOpen();
using (var conn = new OleDbConnection(ConnectionString))
{
try
{
conn.Open();
}
}
I gave myself full permissions for the server as well as the .accdb file iteself, and did the same for the NETWORK SERVICE account as per this post, but still not luck.
I don't have a problem connecting to databases which are stored locally, and this only seems to be happening whent rying to conect over the network.
Has anyone else experienced this and found a solution? Any help or advice is much appreciated.
I have checked this answer and can confirm that I have all the required permissions to access the file.
That question is marked as a duplicate of this question, but I don't have any programs running which would have a stream open to the file.

It turns out this was being caused by trying to work with some terrible IT infrastructure.
The issue is that \\ACCESSSERVER-PC is actually a Windows 7 machine and so can only handle a limited number of connections.
Running the IsLocked code from this answer against the database file gave me a much more useful error message:
No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.
After getting some users to disconnect their Access runtime and mapped drives from the server and running the code again, IsLocked returned false and I was then able to connect to the database.
Here is the code I used to help me find the solution to this:
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
//
// ** OR There are already too many connections open to the
// ** "server" where the file exists!
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
The moral of the story is Don't use (or work in an environment where they use) a Windows 7 machine as a server when you need 20+ concurrent connections to the server!

Related

MySql exception on Windows 10: SocketException with ErrorCode 10053

I have a small application which is trying to import data from a MySql database into a SQL Express database. This is under development in Visual Studio 2013 on Windows 10, using Entity Framework Database First to model the MySql database, connect to it and retrieve the data.
The software is being developed TDD, so I have an NUnit test which is checking that the application can successfully connect to the MySql database and retrieve data from it. One test is very simple, as follows:
[Test]
public void MySqlContext_CanConnectToLegacyDb_OpensWithoutErrors()
{
// Arrange
using (MySqlContext legacyRepository = new MySqlContext())
{
bool exceptionThrown = false;
List<string> exceptionMessages = new List<string>();
// Act
try
{
legacyRepository.Database.Connection.Open();
}
catch (Exception ex)
{
exceptionThrown = true;
exceptionMessages.Add(ex.Message);
while (ex.InnerException != null)
{
ex = ex.InnerException;
exceptionMessages.Add(ex.Message);
if (ex is SocketException)
{
exceptionMessages.Add(string.Format("ErrorCode={0}", (ex as SocketException).ErrorCode));
}
}
}
// Assert
StringBuilder errMsg = new StringBuilder("Exception was thrown: ");
foreach(string em in exceptionMessages)
{
errMsg.AppendLine(em);
}
Assert.IsFalse(exceptionThrown, errMsg.ToString());
}
}
Ie. it is simply checking that it can open the connection to the MySql database without any exceptions being thrown.
This test is failing. The attempt to open the MySql database produces the following exception:
Result Message: Exception was thrown: Unable to read data from the
transport connection: An established connection was aborted by the
software in your host machine. An established connection was aborted
by the software in your host machine ErrorCode=10053
Expected: False
But was: True
MySql is running on the same machine as this test and of the application that it is supporting. It is in use by other software on the machine, including MySql Workbench and the Server Explorer of the same Visual Studio instance, without any connectivity problems. I have checked and re-checked the connection string being used to access the database, and it is the same one that was generated by Entity Framework when it generated the model for the database.
Based on what I've read about this exception online, I have made a thorough check of all of the security settings on Windows 10, I have reviewed MySql logs and other logs, including the Windows event logs. I can find nothing in any log which hints at what is aborting the connection with MySql. Fiddler does not show anything when the offending line of code fails, so I can see no evidence of anything trying to talk to MySql via the localhost/127.0.0.1 connection.
I've tried disabling those settings that I can find, and disabling by BitDefender anti-virus software, and none of those actions has any effect on this error.
What else can I check, to find out the cause of this error? Could it be a security setting within Windows?
Some further information:
Prompted by something I read elsewhere about EF Database First, I tried deleting the MySql model from my solution and re-adding it, to see if this changed anything in the connection string. This time through, the ADO.NET Entity Data Model wizard dies, with no errors, when I click Next on the Choose Your Data Connection screen (3rd screen). When it does this, the Server Explorer connection to the MySql database closes (the icon shows a red cross, when it was showing a green plug).
I'm now thinking that there is some configuration problem, somewhere in my solution. But how to diagnose the problem? I get no error messages, when the wizard dies, and the Output window shows nothing.
Another update:
I think the problem might be down to MySql configuration issues. I appear to have 2 or possibly 3 "my.ini" settings files for MySql, and I suspect that the one being maintained by the MySQL Workbench is not the one that the server is actually using for its configuration. Why do I think this? Because, when I enabled logging for various items that are not logged by default (why not?), no change in behaviour happened. MySql did not begin writing log files - until I copied the my.ini file that had been changed by the utility (C:\Program Files\MySQL\MySQL Server 5.5\my.ini) over the file that was in C:\ProgramData\MySQL\MySQL Server 5.5. After I did that, MySQL started logging stuff, but then I could not connect to the server properly via the Workbench.
I am investigating further, and will post what I find here, in case anyone else has a similar problem.

Connect to database in network drive

I am a newbie to SQL Server and .net. Please let me know if my question is not clear before down voting.
I am working on a Windows application with C#. I should give option to users to connect to a .mdf file on a network drive. On my machine, I have Windows and SQL Server authentication. Users have SQL authentication hence I should use userid and pwd. Myself and users work on that network drive, read/write/modify. We pretty much share documents, add and delete docs from network drive.
Here is the designer
I will choose the SQL Server database .mdf file which is located in network drive and then do test connection. For Test Connection this is the code
string sTemp = System.Configuration.ConfigurationManager.AppSettings["connectionStringShare"];
string connectionString = sTemp.Replace("{AppDir}", txtDB.Text.Trim());
using (SqlConnection objSqlConnection = new SqlConnection(connectionString))
{
try
{
objSqlConnection.Open();
objSqlConnection.Close();
MessageBox.Show("Connection is successfull");
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message.ToString());
}
}
This is the connection string
<add key="connectionStringShare"
value="Data Source=.\SQLEXPRESS;Initial Catalog=TableSQLExpress;AttachDBFilename={AppDir};Integrated Security=SSPI;user id=sa;password=pwd;" />
Here is the error message I got
Directory lookup for the file "S:\zrep\TableSQLExpress.mdf" failed with the operating system error 3(The system cannot find the path specified.).
Cannot attach the file 'S:\zrep\TableSQLExpress.mdf' as database 'TableSQLExpress'.
I changed connection string and tried also tired using windows authentication. No luck. Let me know if I need to provide any additional details. Since I am newbie to this field please give me detailed answer. I am glad to find this group. Thanks for everyone who looked into this.
When you use server-based SQL Server (i.e. Microsoft SQL Server Express) you are unable to share database file via network drive, it is by design. Even if you override default SQL Server behavior with a switch and enable UNC paths for databases, your data will be corrupted by multiple server instances trying to use single database MDF file. If you need to host database in serverless environment (using only a network drive), you may opt to Microsoft SQL Server Compact (SQL Server CE) edition. But be aware that in such case only one user will be able to access database file at the same time (exclusive locking -> low performance). Plus SQL Server CE does not have stored procs.

Unable to complete network request to host "psf" using firebird embedded depending of the directory

I'm trying to connect to a embedded firebird database using de following code:
var cmm = new FbCommand();
var csb = new FbConnectionStringBuilder();
csb.ServerType = FbServerType.Embedded;
csb.UserID = "SYSDBA";
csb.Password = "masterkey";
csb.Dialect = 3;
csb.Charset = "UTF8";
csb.Database = #"TESTE.FDB";
cmm.Connection = new FbConnection(csb.ConnectionString);
try
{
cmm.Connection.Open();
cmm.CommandText = "SELECT NOME FROM TESTE WHERE ID=2";
MessageBox.Show(Convert.ToString(cmm.ExecuteScalar()));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
cmm.Connection.Close();
}
The query execute depending of the directory of the program. If I open the program in the directory "C:\np" or other local directory, it works normally. But, if the directory is a network mapping, I receive the following error: "Unable to complete network request to host "psf". Failed to establish a connection."
What can I do to resolve this situation? Thanks.
Firebird doesn't allow opening databases on network shares by default, as this could lead to database corruption as Firebird needs either exclusive access to a database, or instances sharing a database file need to coordinate access using a lock file local to the server. Access through a network share means that multiple instances from multiple hosts could access the same database file, and that is not how Firebird is designed to be used.
If you want to access a single Firebird database from multiple hosts then you should setup a Firebird server and configure all clients to connect to that server, you should not use a network share.
However if you really want to access a database on a network share, then you can set the option RemoteFileOpenAbility in firebird.conf to 1. Given the risk of file corruption and data loss I strongly advise not to use this option, but use a Firebird server instead. Make sure you read the warning in the config file as well.

Using Smo.Backup to backup SQL Server database to string

I'm trying to make a little app that would help me making my server backup. That app would run on my home PC so the main goal is to be able to connect to the external server, backup the selected database, dump the backup content to a string or something so I could write it on my PC disk and not the server's disk.
I did that which works to write on the server's disk, but I'd like to be able to write on my PC's disk the backup's result.
private bool BackupDatabase()
{
try
{
// Filename
string sFileName = string.Format("{0}\\{1}.bak", _sWhereToBackup, DatabaseName);
// Connection
string sConnectionString = String.Format(
"Data Source=tcp:{0};Initial Catalog={1};User ID={2};Pwd={3};",
DatabaseHost, DatabaseName, DatabaseUsername, DatabasePassword);
SqlConnection oSqlConnection = new SqlConnection(sConnectionString);
Server oServer = new Server(new ServerConnection(oSqlConnection));
// Backup
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = DatabaseName;
backup.Incremental = false;
backup.Initialize = true;
backup.LogTruncation = BackupTruncateLogType.Truncate;
// Backup Device
BackupDeviceItem backupItemDevice = new BackupDeviceItem(sFileName, DeviceType.File);
backup.Devices.Add(backupItemDevice);
// Start Backup
backup.SqlBackup(oServer);
}
catch (Exception ex)
{
throw ex;
}
return false;
}
Thanks so much!
This is going to get a bit hacky because you need to either
call sql functions to read the file on the server and return as a binary array to you and then convert back to a file. this will require proper permissions as the account you are running under to access the file on the server's drive.
you can use t-sql or a bit more 'advanced' .net code
t-sql can be seen in this great sql injection guide
http://www.blackhat.com/presentations/bh-europe-09/Guimaraes/Blackhat-europe-09-Damele-SQLInjection-slides.pdf
or .net:
http://www.mssqltips.com/sqlservertip/2349/read-and-write-binary-files-with-the-sql-server-clr/
map a file location (i.e. access a share/drive/ipc connection) over the network
have the server ftp the files to a location
Which sounds likely in your scenario?
I take it that you're not networked to the server? Ideally you could back it up directly to your machine using a network address but I'm guessing you would have already thought of that.
Going the route you're thinking of is going to require you to have permissions that you would not normally want to have opened up to the someone over the internet, and will be much more trouble to program than simply setting up a second process to move the file somewhere accessible to you.
Adams suggestion to have the server ftp the files is a good one. Alternatively, you may find that using DropBox (www.dropbox.com) might be the path of least resistance. Then you could just back the database up to a folder setup with dropbox and it will automatically be copied to any folder you setup on your machine to be synchronized with it.
You should look into DAC, it is mainly made for the SQL Server in Azure, but will work with a SQL Server 2008 R2 too.
http://sqldacexamples.codeplex.com/

How to store file on server ASP.net

Ok so I am trying to have error log file for the website running on ASP.net and C#.
I tried storing to drive with regular path.
Expecting it because it is in c# code (code behind page) it will pick up the server and store it there. (In the end it is a code that gets executed on server)
Unfortunatelly for me thats not true. It gets saved on local machine from which client opens the site.
How can you force it to be saved on server machine?
I want all of the error logs on one place.
Any suggestions on reading or how to do this.
string path = "C:\\WebSite";
string error = "error";
try
{
// check if dir exists if it does i add file name to the path
// i removed code to keep it simple
path += "\\logs.txt";
FileStream log_fs =
new FileStream(path, FileMode.Append, FileAccess.Write);
StreamWriter log_sw =
new StreamWriter(log_fs);
string log = String.Empty;
// formate log string using error message
log_sw.Write(log);
log_sw.Close();
log_fs.Close();
}
catch (Exception ex)
{
// here I e-mail the error in case logging failed
}
This code will generate file on local machine, instead of server
You can log to any location on the web server (that the ASPNET user account has permission to write to) with code such as this:
string log = String.Empty;
// format log string using error message
try
{
using (StreamWriter logFile = new StreamWriter(#"C:\WebSite\logs.txt", true))
{
logFile.WriteLine(log);
}
}
catch
{
// here I e-mail the error in case logging failed
}
This will write the file to the web server hosting the website. Now, if you're running the website locally during development and you're using either the built-in VS webserver or IIS, then of course the file will be created on your machine when testing the website locally.
To answer the suggestion portion of your question, have you considered using ELMAH, it will log errors to different storages:
Microsoft SQL Server
Oracle (OracleErrorLog)
SQLite (version 3) database file
Microsoft Access (AccessErrorLog)
VistaDB (VistaDBErrorLog)
Loose XML files
RAM (in-memory)
or send via email, twitter
elmah is very easy to setup and very effective

Categories

Resources