Unable to open SQLiteConnection on the network directory in c# - c#

Using C#, .Net framework 4.8, SQLite 1.0.115
I am using System.Data.SQLite.SQLiteConnection to open a sqllite database on the network drive. But it fails with "unable to open database file". While debugging it I found that it is always pointing to the local drive instead of the network.
example: I have provided "\\NW\test\DB\test.sqlite" as a data source in the connection string. But when I see an exception it says can't find the file in "C:\NW\test\DB\test.sqlite". My program runs on C: drive.
private SQLiteConnection _connection;
var builder = new SQLiteConnectionStringBuilder
{
DataSource = "\\\\NW\\test\\DB\\test.sqlite",
Version = 3,
ForeignKeys = true,
};
var connectionString = builder.ConnectionString;
if (_connection == null)
{
_connection = CreateConnection(connectionString );
_connection.Open();
}
return _connection.BeginTransaction(isolationLevel);
On connection open, I am getting this exception
SQLite error (14): os_win.c:47688: (3) winOpen(C:\NW\test\DB\test.sqlite) - The system cannot find the path specified.
Does anyone know why it is pointing to a local drive instead of the network?

By doing multiple trials and errors this change fixed the issue
private SQLiteConnection _connection;
var builder = new SQLiteConnectionStringBuilder
{
DataSource = #"\\\\NW\\test\\DB\\test.sqlite",
Version = 3,
ForeignKeys = true,
};
var connectionString = builder.ConnectionString;
if (_connection == null)
{
_connection = CreateConnection(connectionString );
_connection.Open();
}
return _connection.BeginTransaction(isolationLevel);
So, in the Datasource it needs "\\\\\\\\NW\\test\\DB\\test.sqlite" path. Not sure why so many back slashes but this fixed the problem.

Related

How to backup a database in WPF with C# and SQL Server? [duplicate]

This question already has answers here:
Backup Permissions
(5 answers)
Closed 1 year ago.
I'm trying to back up my database using this C# code How to backup and restore SQL Server in WPF with C# and Entity Framework
private static void CreateBackup(string databaseName, string backupFilePath)
{
GlobalConfig gb = new GlobalConfig();
string connectionString = gb.GetConnectionString();
backupFilePath = backupFilePath + "\\" + databaseName + ".bak";
backupFilePath = #""+backupFilePath;
var backupCommand = "BACKUP DATABASE #databaseName TO DISK = #backupFilePath";
using (var conn = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(backupCommand, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("#databaseName", databaseName);
cmd.Parameters.AddWithValue("#backupFilePath", backupFilePath);
cmd.ExecuteNonQuery();
}
}
CreateBackup("Test","C:\Desktop\Backup\\Test.bak");
But I got this error :
Cannot open backup device 'C:\Desktop\Backup\Test.bak'. Operating system error 5(Access is denied.).
What I'm doing wrong with this code?
How can I fix this error?
The SQL Server process typically does not run with the permissions of the currently logged in user, therefore it cannot access the users desktop (nor most of the folders of the user or any network folders). It is not possible to freely choose the folder for the backup.
Your best solution is to export to a folder where the server process has access to (i.e. the system temp folder) and then copy the backup from there to wherever you want it.
private static void CreateBackup(string databaseName, string backupFilePath)
{
GlobalConfig gb = new GlobalConfig();
string connectionString = gb.GetConnectionString();
// Create the backup in the temp directory (the server should have access there)
var backup = Path.Combine(Path.GetTempPath(), "TemporaryBackup.bak");
var backupCommand = "BACKUP DATABASE #databaseName TO DISK = #backup";
using (var conn = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(backupCommand, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("#databaseName", databaseName);
cmd.Parameters.AddWithValue("#backup", backup);
cmd.ExecuteNonQuery();
}
File.Copy(backup, backupFilePath); // Copy file to final location
}
I have successfully backed up SQL Server databases using Microsoft.SqlServer.Management.Smo.Backup, might want to try that. Mine was in VB years ago but it is still working today. Here is the VB code if it helps:
Dim mySourceServer As New Server(My.Settings.SQLInstance)
Dim bkpDBFullWithCompression As New Backup()
' Specify whether you want to back up database or files or log
Me.Cursor = Cursors.WaitCursor()
bkpDBFullWithCompression.Action = BackupActionType.Database
' Specify the name of the database to back up
bkpDBFullWithCompression.Database = _sBackupDatabaseName
bkpDBFullWithCompression.CompressionOption = BackupCompressionOptions.[On]
bkpDBFullWithCompression.Devices.AddDevice(_sBackupFilePath, DeviceType.File)
bkpDBFullWithCompression.BackupSetName = _sBackupDatabaseName + " database Backup - Compressed"
bkpDBFullWithCompression.BackupSetDescription = _sBackupDatabaseName + " database - Full Backup"
Try
bkpDBFullWithCompression.SqlBackup(mySourceServer)
Catch ex As SmoException
blSuccess = False '
Me.Cursor = Cursors.Default
End Try
This solution ( Check Local System account instead of This account ) worked for me, but I didn't have any idea if it's a good solution for security or no.
You can find the LogOn tab setting under this :
Services -> SQL Server -> Properties -> Log on

ODP.NET Managed library does resolve alias, but 32-bit library does

I have 32-bit drivers installed on my box (they were installed and configured by some DBAs)
I wrote a simple script to test the drivers which pretty much is as follows
using (DataTable table = new DataTable())
{
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = "Data Source=alias;User id=user;Password=password";
connection.Open();
using (OracleCommand command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = "SELECT * FROM DUAL";
table.Load(command.ExecuteReader());
}
}
}
When I compile this application as 32-bit with the 32-bit Oracle.DataAccess.dll, it executes without a hitch.
However if I compile the application as AnyCPU with the Oracle.ManagedDataAccess.dll, i get an ORA-12154 (could not resolve the connect identifier specified) error.
If I tnsping alias, it works correctly and tells me the connect identifier with the real database name.
If I then change the connection string to use the real database name instead of the alias, and then try with the managed library again, it executes without a hitch.
I've been reading around and found this answer which says the managed driver relies on the tnsnames.ora file to resolve the aliases, however I rely on LDAP servers defined in sqlnet.ora and ldap.ora.
When I tnsping, it says it uses sqlnet.ora to resolve the name.
So how come the managed drivers do not work?
May this workaround is suitable for you. You can query the LDAP server by your own and put the full connection string to your code.
You can resolve the connection string from LDAP with this code:
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = "Data Source=" + ResolveServiceNameLdap("alias") + ";User id=user;Password=password";
connection.Open();
}
...
private static string ResolveServiceNameLdap(string serviceName)
{
string tnsAdminPath = Path.Combine(#"C:\oracle\network", "ldap.ora");
// or something more advanced...
// ldap.ora can contain many LDAP servers
IEnumerable<string> directoryServers = null;
if ( File.Exists(tnsAdminPath) ) {
string defaultAdminContext = string.Empty;
using ( var sr = File.OpenText(tnsAdminPath) ) {
string line;
while ( ( line = sr.ReadLine() ) != null ) {
// Ignore comments or empty lines
if ( line.StartsWith("#") || line == string.Empty )
continue;
// If line starts with DEFAULT_ADMIN_CONTEXT then get its value
if ( line.StartsWith("DEFAULT_ADMIN_CONTEXT") )
defaultAdminContext = line.Substring(line.IndexOf('=') + 1).Trim(new[] { '\"', ' ' });
// If line starts with DIRECTORY_SERVERS then get its value
if ( line.StartsWith("DIRECTORY_SERVERS") ) {
string[] serversPorts = line.Substring(line.IndexOf('=') + 1).Trim(new[] { '(', ')', ' ' }).Split(',');
directoryServers = serversPorts.SelectMany(x => {
// If the server includes multiple port numbers, this needs to be handled
string[] serverPorts = x.Split(':');
if ( serverPorts.Count() > 1 )
return serverPorts.Skip(1).Select(y => string.Format("{0}:{1}", serverPorts.First(), y));
return new[] { x };
});
}
}
}
// Iterate through each LDAP server, and try to connect
foreach ( string directoryServer in directoryServers ) {
// Try to connect to LDAP server with using default admin contact
try {
var directoryEntry = new DirectoryEntry("LDAP://" + directoryServer + "/" + defaultAdminContext, null, null, AuthenticationTypes.Anonymous);
var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectclass=orclNetService)(cn=" + serviceName + "))", new[] { "orclnetdescstring" }, SearchScope.Subtree);
SearchResult searchResult = directorySearcher.FindOne();
var value = searchResult.Properties["orclnetdescstring"][0] as byte[];
if ( value != null )
connectionString = Encoding.Default.GetString(value);
// If the connection was successful, then not necessary to try other LDAP servers
break;
} catch {
// If the connection to LDAP server not successful, try to connect to the next LDAP server
continue;
}
}
// If casting was not successful, or not found any TNS value, then result is an error
if ( string.IsNullOrEmpty(connectionString) )
throw new Exception("TNS value not found in LDAP");
} else {
// If ldap.ora doesn't exist, then throw error
throw new FileNotFoundException("ldap.ora not found");
}
return connectionString;
}
ODP.NET Managed driver relies on TNS_ADMIN value being set in the config file to find the TNSNAMES.ORA file. If you don't want to set that value, you can include the TNSNAMES.ORA file in the working directory of the executable or create a TNS alias in the config file directly.
Edit: If you are relying on SQLNET.ORA and LDAP.ORA you can also copy those into the working directory as well, or set the LDAP parameters in your config file. See the ODP.NET doc for the config file parameters available for LDAP.

SQL Server CE connecting string not allowing for data insertion

OK, I've been working on this since late last night and early this morning. I am trying to insert some data into a SQL Server CE database. I am at the end of my rope.
Here is the code I am trying to implement:
public static void InsertData(string sqlStatement)
{
try
{
//string strConn = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
//string StartupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Remove(0, 6); // remove file:\\
//string connectionString = #"Data Source=Database1.sdf";
//string connectionString = #"Data Source = |DataDirectory|\Database1.sdf";
//string connectionString = #"Data Source = C:\Users\My\Documents\Visual Studio 2012\Projects\VIN_Decoder\VIN Decoder\VIN Decoder\Database1.sdf"
//string connectionString = string.Format("Data Source={0}; Persist Security Info=False;", Path.Combine(Application.StartupPath, "Database1.sdf"));
//THIS ONE ACTUALLY WORKS!!!!!!!!!!!! :
//string connectionString = #"Data Source = C:\Users\My\Documents\Visual Studio 2012\Projects\VIN_Decoder\VIN Decoder\VIN Decoder\Database1.sdf"
string connectionString = Properties.Settings.Default.Database1ConnectionString;
SqlCeConnection sqlceCon = new SqlCeConnection(connectionString);
sqlceCon.Open();
SqlCeCommand sqlCeCom = new SqlCeCommand(sqlStatement, sqlceCon);
sqlCeCom.ExecuteNonQuery();
sqlCeCom.Dispose();
sqlceCon.Close();
}
catch (Exception e)
{
}
}
You can see all of the commented connection strings to see what I have tried. The strange thing is that I can simply use the following connection string in another method (a SELECT statement, not an INSERT INTO statement) that gets a single value from the data and it works fine.
string connectionString = #"Data Source = |DataDirectory|\Database1.sdf";
I have tested the query directly and like the comment says, the static path does work so that tells me my query is good. But of course I need something relative for publishing and multi-developer development.
Most of the connection strings I have tried allow the try block to complete with no errors, but the data doesn't get inserted.
Any suggestions?
I searched my heart out before posting this question, but Simon is right about similarity. However, we're going to have a better answer here. Corak is correct. I set property to not copy, deleted copy in bin\debug folder and app wouldn't run in debug mode because it couldn't find db even though paths all point to other file location. App is looking for copy in bin\debug. Ultimately, it was working all along. I recommend someone to make a connection to the copy in bin\debug so they can test values in the Server Explorer. Thanks for your help Corak and everyone else.
/*If your solution is web application, make sure Database1.sdf location path is under the
* App_Data folder
* Web.Config <add name="LocalDB" connectionString="Data Source=|DataDirectory|\Database1.sdf"/>
*/
protected string ConnString
{
get
{
return ConfigurationManager.ConnectionStrings["LocalDB"].ToString();
}
}
/*
* or you can use try absolute path as connectionstring
* modify your directory path as PhysicalApplicationPath result
*/
public string BaseDirConnString
{
get
{
if ((HttpContext.Current == null) || (HttpContext.Current.Request == null))
{
throw new ApplicationException("...");
}
return #"Data Source=" + HttpContext.Current.Request.PhysicalApplicationPath + "VIN Decoder\\Database1.sdf";
}
}
protected SqlCeConnection SqlCeConnection
{
get
{
var connection = new SqlCeConnection(BaseDirConnString);
connection.Open();
return connection;
}
}

Sqlite connecting to remote file using url C#

ive been trying to get my sqlite to read a remote file but is just flatout tells me this isnt supported is there a workaround for this ?
here is the function that gives the error
public void Run(string sql,string check,string file)
{
SQLiteConnection m_dbConnection;
string test = "Data Source=" + file + ";Version=3;";
m_dbConnection = new SQLiteConnection(test);
m_dbConnection.Open();
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
if (check == "0")
{
while (reader.Read())
comboBox1.Items.Add(reader["name"] + "." + reader["TLD"]);
comboBox1.SelectedIndex = 0;
}
else
{
proxy = reader["proxyip"].ToString();
check = "0";
}
}
error i get is "URI formats are not supported"
the file variable is filled by one of 2 values.
string filelocal = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\unblocker\\sites.db";
or
string remotefile = "http://127.0.0.1/test.db";
the one that gives the error is the remote file.
The Connection string uses as a datasource the db file which is expected on your local file system, take a look at this example code.
You can transorfm this using:
Uri uriFormatted = new Uri(file);
uriFormatted.AbsolutePath; // Try to use this value instead to call your function
EDIT
SQLite is a local standalone database, that is used for standalone software
Consider using SQLitening:
SQLitening is a client/server implementation of the popular SQLite database.

sqlite c#: database connection not valid

I have a sqlite database file in .s3db, It has all the tables and data already populated in it. I am trying to connect to to the database use sqliteConnection. But it does not seem to work..I have added the reference of sqlite.dll, does c# needs some other reference to make the connection? If I make a new sqlite db, it is made as xyz.sqlite, maybe it is not recognizing the database extension.
This is how I am making the connection:
// Creates a connection with our database file.
public void connectToDatabase()
{
//this.dbConnection = new SQLiteConnection(#"data source=Fut_Autobuyer_2012.s3db;version=3;");
string dbConnectionString = #"Data Source=Fut_Autobuyer_2012.s3db";
this.dbConnection = new SQLiteConnection(dbConnectionString);
}
This is what I get when the connection is made:
Database connection not valid for getting number of changes.
Database connection not valid for getting last insert rowid.
Database connection not valid for getting maximum memory used.
Database connection not valid for getting memory used.
It looks like you must open database connection:
using (var connection = SQLiteFactory.Instance.CreateConnection())
{
Debug.Assert(connection != null, "connection != null");
connection.ConnectionString = connectionString;
connection.Open();
try
{
using (var command = connection.CreateCommand())
{
// Execute connection
}
}
finally
{
connection.Close();
}
}

Categories

Resources