I am creating an app for my work to track behavior management over the course of a school year. To do this, I obviously needed a database. I built the program so that it would, when opened, check to see if the database exists, and if it doesn't, it creates one, and inputs the schema. This works perfectly on my dev computer, but when I switch it to a computer using windows XP it gives an error saying system.io.filenotfoundexception. I can't figure out why it won't create the database.
I am using Visual C# 2010 Express. And the database is made in sql server ce.
if (!File.Exists("chart.sdf"))//Checks if file is already in existance when app is opened
{
dbCreated = createDb();//If there is no database, creates one
}
public bool createDb()//Creates the database if needed
{
bool success = true;
//Holds sql schema for the table
string[] tableCreateArr ={"create table childNameId"
+ "(childId INT IDENTITY PRIMARY KEY, "
+ "childFName nchar(40), "
+ "childLName nchar(40));",
"create table leaderNameId"
+ "(leaderId INT IDENTITY PRIMARY KEY, "
+ "leaderFName nchar(40), "
+ "leaderLName nchar(40));",
"create table TagPulledId"
+ "(tagId INT IDENTITY PRIMARY KEY, "
+ "childId INT, "
+ "leaderId INT, "
+ "day TINYINT, "
+ "month TINYINT, "
+ "year INT);",
"CREATE TABLE tagInfo"
+ "(tagId INT, "
+ "color nchar(10), "
+ "description ntext)"};
SqlCeEngine dbCreate = new SqlCeEngine(connectString()); // creates the database obj
dbCreate.CreateDatabase(); // creates the database file
SqlCeConnection tempConnect = new SqlCeConnection(connectString());//Connects to the new database
SqlCeCommand objCmd = new SqlCeCommand();//Creates an sql command obj
tempConnect.Open(); // opens the connection
objCmd.Connection = tempConnect; //Connects the command obj
foreach (string strCmd in tableCreateArr)//Iterates throught he sql schema to create the tables
{
try
{
objCmd.CommandText = strCmd; //sets the CommandText to the next schema entry in the array
objCmd.ExecuteNonQuery(); //Executes the create query
}
catch (SqlCeException sqlError)
{
MessageBox.Show(sqlError.Message, "SQL Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
success = false;
}
}
tempConnect.Close();
return success;
}
I can't figure out why the app isn't making the database, it seems to work on some computers, while not working on others. Any help would be great! Thank you.
if (!File.Exists("chart.sdf"))
You seem to want to create the database in the same directory as your program. Yes, that will work on your dev machine but that's not going to work on a regular machine. The typical install directory (c:\program files\etc) does not permit write access to files.
You will need to use Environment.GetFolderPath() to get an ApplicationData directory that you can write to.
It is often a lot easier and less error prone to let an installer create the appdata directory and copy the initial .sdf file in there. Albeit that Setup projects are not supported by the Express edition. There does come a point where hacking code to work around the Express edition's restrictions is defeating the price of the product license. You're pretty close here.
Make sure you have deployed all the dll Sql Server Compacts need. I'm not sure you get them when you install .NET framework. The dll needed are :
sqlceca35.dll
sqlcecompact35.dll
sqlceer35EN.dll
sqlceme35.dll
sqlceoledb35.dll
sqlceqp35.dll
sqlcese35.dll
You can find more details on this MSDN page about Sql Compact Deployment for various versions of the database engine.
Related
So i have a problem updating record in my database. My code runs without error, but the record is not updated. Here is the code:
private void button3_Click(object sender, EventArgs e)
{
try
{
if (con.State == ConnectionState.Closed)
{
con.Open();
}
string sql = string.Format("update Alternatif set No ='" + textBox1.Text + "',Kecamatan='" + textBox2.Text + "',Kelurahan='" + textBox3.Text + "',Nama='" + textBox4.Text + "'where No ='" + textBox1.Text + "'");
OleDbCommand perintah = new OleDbCommand(sql, con);
perintah.ExecuteNonQuery();
MessageBox.Show("Data edited successfully");
perintah.Dispose();
con.Close();
}
catch (Exception)
{
MessageBox.Show("Data failed to edit");
}
}
I'm assuming you have proven that the query works to update the record in access - you should consider capturing the int that is returned from ExecuteNonQuery and if it is 0, no records were updated
You should also consider having a good read of http://bobby-tables.com and promise yourself never to write an SQL again like you have there. It is prone to sql injection attack and is a massive security issue
Access is a file based database and typically when added to a visual studio there is a dev version of the file (the file as it was when selected for addition to the project) that is copied to the build directory every time a build is run. The app typically updates the build copy in the bin directory, not the dev copy outside the bin directory.
Developers then go looking in the dev copy and are surprised that no change was made- they're looking in the wrong file.
Or they go looking in the build copy, but after another build has been run and the edited db has been overwritten with a fresh, empty copy of the dev db. Search your project folder for all db and ensure you're inspecting the right one
You can stop the build process replacing the bin folder version of the file every time by finding the db in the solution explorer, getting properties on it and setting the Copy To Output Directory to something other than Copy Always. I personally use Copy If Newer
I am currently facing a very strange issue with one of my database instances.
I wrote a small application to backup a set of databases from one MS SQL Server 2008 instance and restore the same set on top of existing DBs on a second instance. Both instances are running on top of Windows Server 2008R2 machines. Backups and restores are done using MS SQL Server Management Objects (SMOs), built into a simple C# Windows Form.
After I restore the DBs on the second instance, I encounter a few issues:
Right-clicking on a database and select Properties gives me the following error message
|-> Cannot show requested dialog (SqlMgmt)
|-> An exception occurred while executing a Transact-SQL statement or batch
|-> Could not continue scan with NOLOCK due to data movement. (Microsoft SQL Server, Error: 601)
I cannot open Activity Monitor (same error message)
SQL Error log reports the Resource DB is corrupted ("SQL Server detected a logical consistency-based i/O error: invalid protection option. It occurred during a read of page ... in database ID ... at offset ... in file ...")
the SELECT SERVERPROPERTY('ResourceVersion') command gives out a version number
copying the mdf and ldf files for the resource DB from another SQL Server (and restarting the services) solved the issues
Now I know the resource DB is supposed to be read-only and outside of HW issues there's no way it can get corrupted, which really has me wondering, where did I mess up? And why does replacing the resource DB fix my issue?
Has anyone ever encountered the same issue?
Update:
Backups are performed with the following commands:
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = databaseName;
backup.CopyOnly = true;
backup.Checksum = true;
backup.BackupSetDescription = "Full backup of " + databaseName;
backup.BackupSetName = databaseName + " Backup";
backup.Initialize = true;
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
backup.Devices.AddDevice(backupFilePath, DeviceType.File);
Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
smoServer.ConnectionContext.StatementTimeout = 0;
smoServer.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
smoServer.ConnectionContext.Connect();
backup.SqlBackup(smoServer);
smoServer.ConnectionContext.Disconnect();
..and verified as follows:
Restore restore = new Restore();
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
BackupDeviceItem deviceItem = new BackupDeviceItem(backupFilePath, DeviceType.File);
restore.Devices.Add(deviceItem);
bool verified = restore.SqlVerify(smoServer);
Restores are performed with:
Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
smoServer.ConnectionContext.StatementTimeout = 0;
smoServer.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
smoServer.ConnectionContext.Connect();
Database db = smoServer.Databases[databaseName];
Restore restore = new Restore();
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
BackupDeviceItem deviceItem = new BackupDeviceItem(backupFilePath, DeviceType.File);
restore.Devices.Add(deviceItem);
restore.Database = databaseName;
restore.Action = RestoreActionType.Database;
restore.ReplaceDatabase = true;
restore.SqlRestore(smoServer);
db = smoServer.Databases[databaseName];
db.SetOnline();
smoServer.Refresh();
db.Refresh();
Restore rest = new Restore();
rest.Devices.AddDevice(backupFilePath, DeviceType.File);
bool verifySuccessful = rest.SqlVerify(smoServer);
smoServer.ConnectionContext.Disconnect();
I know the connection should actually disconnect itself once the backup or restore is complete, and that does actually connect and disconnect correctly, this latest version with manual connect and disconnect was an experiment to check if there was any difference in the end result. There wasn't.
Both backups and restores are executed in a background worker, inside try...catch loops, and no exceptions are raised.
I believe the params are self-explanatory, but if something is unclear I'd be happy to clarify.
Update 2:
After a more thorough round of testing, I was unable to reproduce the resource DB corruption issue. Ergo I am blaming this on planetary alignment when I first tried out the restores.
Thanks Jeroen for the help and the hints!
There's no reason to assume your backup/restore had anything to do with the database failing. Do the usual dance when you encounter corruption: run DBCC CHECKDB, check your hardware for errors, see if there are cumulative updates applying to your version that might resolve corruption issues. If you can consistently reproduce the error by restoring your databases, even on another machine with the exact same version of SQL Server, you may have found a bug MS is interested in. Otherwise, I'd take a long, hard look at the hardware.
The fact that replacing the resource database fixed it does not in any way imply you've found and fixed the underlying problem, just that it's not corrupted anymore. This still tells you nothing about the cause of the corruption.
And just for completeness: nothing you do short of manually editing database files (through DBCC PAGE or just by writing to it outside SQL Server) is a legitimate reason for database corruption, so you definitely didn't "mess up".
I am having a weird problem. I am using vs2012 to connect to SQL Server CE and executing some insert queries.
public void EstablishConnection()
{
connection = new SqlCeConnection("Data Source=DataDump.sdf;Persist Security Info=False;");
try
{
connection.Open();
Console.WriteLine("Connection Successful");
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
public void AddRecord(string link,string content)
{
int num = 0;
var command = new SqlCeCommand("INSERT INTO Webpages(Link,Data) VALUES('"+link+"','"+content+"');",connection);
num = command.ExecuteNonQuery();
Console.WriteLine("Command Successful rows affected"+num);
var cmd2 = new SqlCeCommand("SELECT * FROM Webpages",connection);
SqlCeDataReader reader = cmd2.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader[0]);
Console.WriteLine(reader[1]);
}
}
However I am having the problem that once VS is closed and when later I open it to display the data, the data is gone as it was never saved
How is that possible when it is clear then it executed the query?
It is a common scenario.
You have your database file listed between your project items.
Its property Copy to Output directory is set to Copy Always.
Now, you run your debug session with VS. The compile is succesfull and VS copies your sdf file from the project folder to the current output directory (BIN\DEBUG).
Your code runs smoothly and inserts the data in your database file (on the output directory).
You stop and restart the debug session to fix something, but, at restart, the VS recopies the empty file from the project folder to the output directory.
To break this circle, set Copy to Output Directory to Copy Never (or Copy if Newer)
EDIT Another source of confusion is due to the use of SERVER EXPLORER to view the contents of your database file. If the server explorer use a connection string that points to the database file in the project folder you never see the changes made to the database file in the Output Directory.
You should create two connections in Server Explorer, one named DEBUG DataDump that points to PROJECTFOLDER\BIN\DEBUG. You could use this connection to check the data inserted during debug or for other debugging tasks. Another one, called DISTRIBUTION DataDump, points to the file in the project folder and you make here your schema changes needed for the distribution of your app.
Said that, keep in mind that your code has a BIG problem. It is called Sql Injection
A parameterized query will avoid quotations problems and remove the Sql Injection
int num = 0;
var command = new SqlCeCommand("INSERT INTO Webpages(Link,Data) " +
"VALUES(#lnk, #cnt)",connection);
command.Parameters.AddWithValue("#lnk", link);
command.Parameters.AddWithValue("#cnt", content);
num = command.ExecuteNonQuery();
set Copy to Output Directory property as Copy if newer for your sdf file
it seems now you have set it as copy always which result :
The database file is copied from the project directory to the bin
directory every time that you build your application. Any changes made
to the data file in the output folder are overwritten the next time
that you run the application.
I have the following code to determine a SQL Server database's compatibility level:
Microsoft.SqlServer.Management.Smo.Server server = new Server(myServerName);
if (!server.Databases.Contains(database))
{ throw new ArgumentException("Specified database ('" + myDBName+ "') not found on '" + myServerName + "'"); }
string connstr = string.Format("Data Source={0};" +
"Persist Security Info=False;" +
"User ID={1};" +
"Password={2};Enlist=False;", myServerName, username, password);
server.ConnectionContext.ConnectionString = connstr;
Microsoft.SqlServer.Management.Smo.Database db = server.Databases[myDBName];
DataSet ds = db.ExecuteWithResults(#"select compatibility_level
from sys.databases where name=db_name()");
I have two users, one of which is able to run this code and get the proper value back. Another user runs this code connecting to the same Server/Database with the exact same credentials and the DataSet returned contains no rows.
What could possibly be the difference between the two users that would cause one to get no result back for the same query? Is there a better way to get Database compatibility?
By the way, this code runs/works on SQL Server 2005 through 2012.
Edit: I should have pointed out that myServerName, myDBName, username, and password are always the same--the only difference is the two different Windows users running the code.
I suspect that the user who returns results has the VIEW_ANY_DEFINITON permission granted to his login. Grant this permission to the other user and he should get the results back.
I'm attempting to connect two SQLite databases in a Unity3d project and I am running into some trouble.
My database paths and file names are correct (checked and confirmed), and I am able to query/insert/etc... from each of the databases individually. However, when I run the ATTACH command, it returns an error stating that my SQL logic is invalid. I have looked at many references and examples, all of which indicate that my command should run as anticipated.
Here is some relevant code:
//open TEMP database
DBAccess.OpenOrCreateDB("/Resources/Data/SaveGames/" + GameController.user.username +
"/", GameController.user.username + "_TEMP");
//attach SAVEGAME database and transfer data from TEMP database
DBAccess.NonQuery("ATTACH DATABASE '" + Application.dataPath + "/Resources/GameData/"
+ GameController.user.username + "/" + GameController.user.username + DBAccess.DBEXT
+ "' AS LOAD_DB;");
//copy records from TEMP database to save game database
//(omitted because not relevant to issue)
//detach SAVEGAME database
DBAccess.NonQuery("PRAGMA LOAD_DB.journal_mode=delete; DETACH DATABASE LOAD_DB;");
//close database
DBAccess.CloseDB();
The goal with this is to copy the in-game changes database to the player's save game database file.
My error debugging prints out the following:
DBAccess -- Cannot perform command with statement: <ATTACH '/Users/scottwindsor/ADITL/
Assets/Resources/GameData/New User/New User.db' AS LOAD_DB;>
It would seem that my SQL command should work... Any help would be appreciated.
Tech Specs:
Platform: OSX (Lepoard, I think)
Compiler: Unity3D (game engine)
Language: C#
SQL: SQLite3.dll
Using IDBCommand.ExecuteNonQuery() to send non-query commands to the database.
Using IDBCommand.ExecuteReader() to send all other commands/queries to the database.