Create a SQLite database with Monotouch - permission denied - database

I am trying to create a Sqlite database using Monotouch 3.0.3.4. Everything works fine on the iPhone simulator, but I get the following error on the test iPhone:
DataLayer.CreateDatabase Exception: System.UnauthorizedAccessException: Access to the path "/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3" is denied.
Here is the code I am using:
// creates database and tables if they do not exist.
public void CreateDatabase ()
{
string sql = string.Empty;
string dbFileName = "myDatabase.db3";
try {
if (!File.Exists (dbFileName)) {
// create database
SqliteConnection.CreateFile (dbFileName); //This is where the error occurs
Console.WriteLine ("CreateDatabase: Database created.");
...
}
catch (Exception ex) {
Console.WriteLine ("CreateDatabase Exception: " + ex.ToString ());
}
...
I have also tried specifing the personal folder, but that has no effect. What do I need to do to make sure permissions are correct?
Thanks!

Monotouch 3.0.3.4
That's likely MonoDevelop 3.0.3.4. See About MonoDevelop to get the MonoTouch version.
"/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3"
On devices the applications are signed, so their content can't change (without breaking the signature). As such you're not allowed to change things in the .app directory.
You should create (or copy) the database in the Documents directory and then open the database as read-write.
See the linked article for more details.

Related

Windows Forms save to dataset but not table [duplicate]

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.
It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.
Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

SSIS 2008 Script task compile failure: Cannot load script for execution

I'm running SSIS 2008, and I'm getting 'Cannot load script for execution.' error when running the script below. I'm able to build this script when editing script task, but it crashes when I run a package. I've tried multiple variations of this script, for example, instead of declaring c# variable dtss below, I've used DTS.Variables default object, it gave me the same issue. Please note I'm not .NET expert, but I need to create folder programmatically only if it doesn't exist, so I need to use script component. As I can see, it's a very "popular" issue, so I've tried some solutions suggested on this forum, but nothing worked for me.
using System;
using System.IO;
using System.Data;
using Microsoft.SqlServer.Dts;
using Microsoft.SqlServer.Dts.Runtime;
class Test
{
/*protected static Microsoft.SqlServer.Dts.Tasks.ScriptTask.ScriptObjectModel CurrDtsContext;*/
protected static Microsoft.SqlServer.Dts.Runtime.Variables dtss;
public static void Main()
{
// Specify the directory you want to manipulate.
string path = (string)(dtss["ArchivePath"].Value + "\\" + dtss["FacilityName"]);
try
{
// Determine whether the directory exists.
if (!Directory.Exists(path))
{
// Try to create the directory.
DirectoryInfo di = Directory.CreateDirectory(path);
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: ", e.ToString());
}
finally { }
}
}
I've eventually used File System task with property UseDirectoryIfExist=TRUE, this way it doesn't overwrite existing folder and doesn't seem to throw any error if folder already exist.

Can't create sqlite db on production machine

I have a program that works correctly on my computer in Debug mode.
When my program start he create a Sqlite data base file if not exists.
This is ok on my computer.
I create a setup version for production version. The program setup is ok.
But when I start the program (.exe) my db file is not created.
This is the connection string I used :
static string dbDirectopry = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
static string dbName = "MySqliteDb.db";
static string Connexion = Path.Combine(dbDirectopry, #"MySociety\MyApplication\" + dbName);
Hi thanks for your help,
this is the code that create db.
public static void CreateDb(string path)
{
SqLiteHelper sqlite = new SqLiteHelper(path);
try
{
User.CreateTable();
}
catch (Exception e)
{
throw e;
}
}
Normaly if the file doesn't exists he is automaticaly created.
If I try my application in Debug mode with Visual Studio my db is created and I can write into.
But when I deploy my application it doesn't work anymore.
My problem is is there any special directory (for windows) to create de db file?

What is my embedded database location

Hello I am having problems with testing if my embedded datbase exists.
I created a database like follows:
try {
SQLiteConnection.CreateFile("AttendanceDatabase.sqlite");
} catch (SQLiteException ex) {
}
And then I insert tables and data into the tables, everything works fine. When im saving data to the database im using the the connection string as follows:
conn = new SQLiteConnection("Data Source=AttendanceDatabase.sqlite;Version=3;");
Now my problem is everytime I run my program it creates the database over, and I would like to know how to test if the database exists it should not create the database over again.
I see the recomended way to do it is using the next statement:
if (File.Exists())
{
}
and I have tried using it as follows:
if (File.Exists("Data Source=AttendanceDatabase.sqlite;Version=3;")){
MessageBox.Show("File Exists");
}
but it does not want to go into the if brackets and display "File Exists".
So I would like to know what my path should be for my embedded database, that is if thats where my problem lies?
Thanx in advance!
I don't have a ton of context but if you update your check:
var basePath = "C:/<path to file>/";
if (File.Exists(basePath + "AttendanceDatabase.sqlite")){
MessageBox.Show("File Exists");
}
You might have more luck. If you give me more context to how you are running this I can help you with using services to lookup the file path. You can look it up based on assembles, approot, etc.

DB4o database DatabaseFileLockedException

I would like to access the same db file from different programs in parallel. All programs are running on the same VM. Here is the code I use:
private ObjectContainer db;
public DatabaseManager(String dbName) {
ObjectServer server = Db4oClientServer.openServer(Db4oClientServer
.newServerConfiguration(), dbName, 0);
try {
db = server.openClient();
// Do something with this client, or open more clients
} catch(Exception ex) {
ex.printStackTrace();
}
}
When I run the second program I get DatabaseFileLockedException. How to use this db in parallel?
Only one db4o instance can access the database file at the same time. If you try to reopen it while a object container has it open you will get this DatabaseFileLockedException.
Within the same JVM instance you can open new session containers like this:
ObjectContainer rootContainer = // the one you've opened the file with
ObjectContainer session = rootContainer.ext().openSession()
With your code you also can use the .openClient() method to do the same. However you actually don't need the client server stuff as long as you're in the same JVM instance. You can use the stuff above with a regular embedded object container.
In case you need to access the same database from multiple databases, then you need a full blown client-server setup.

Resources