连接后对 SQLite 的更改将丢失。Close()

发布于 2024-09-12 01:57:28 字数 1934 浏览 3 评论 0原文

在 iPhone 上使用 MonoTouch .NET,在 Mac OSX 上使用 SQLite。我可以从数据库读取没有问题。但是,当我尝试更改数据库时,我遇到了奇怪的行为。下面的代码运行没有异常,但没有对数据库进行任何真正的更改。我可以创建一个表,插入一条记录,选择该记录,然后将其显示在控制台中。但是,当我关闭数据库连接时,所有这些更改都会消失。此外,如果我在 conn.Close() 之前的代码中放置断点并检查数据库,则该表不存在。听起来我只是在使用一个响应实际 SQL 语句的虚构数据库。诡异的。

这段代码运行但实际上并没有向数据库写入任何内容:

const string _connectionString = "Data Source=App_Data/MyDatabaseFile";

var conn = new SqliteConnection(_connectionString);
conn.Open();

var command = conn.CreateCommand();

command.CommandText = "CREATE TABLE Test (id integer primary key AUTOINCREMENT, text varchar(100))";
command.ExecuteNonQuery();

var cmd2 = conn.CreateCommand();
cmd2.CommandText = "INSERT INTO Test (Text) Values ('test test test')";
var rowsAffected = cmd2.ExecuteNonQuery(); //rowsAffected is 1

var cmd3 = conn.CreateCommand();
cmd3.CommandText = "SELECT * FROM Test";
var reader = cmd3.ExecuteReader();
Console.WriteLine(reader["text"]); //writes "test test test" to console, nothing in database

conn.Close();

如果我在 SQLite 浏览器中执行相同的 SQL 语句,它们工作得很好:

CREATE TABLE Test (id integer primary key AUTOINCREMENT, text varchar(100));
INSERT INTO Test (Text) Values ('test test test');
SELECT * FROM Test;

... 产量 { id = 1, text = 'test test test' }

您可能会知道,但值得一提的是我没有使用交易。

更新:

有趣...我可以更改上面运行 SELECT 查询的代码以查找“Test2”(不存在的表),它会抛出 SQLiteException:“没有这样的表:Test2”。

我还尝试将上面的代码包装在事务中,以防 SQLite 需要事务......没有骰子。

更新#2:

Adam 建议在停止应用程序之前尝试打开一个新连接并再次从新表中进行 SELECT。我在上面的代码之后添加了以下代码:

var conn2 = new SqliteConnection(_connectionString);
conn2.Open();
var cmd4 = conn2.CreateCommand();
cmd4.CommandText = "SELECT * FROM Test";
var reader2 = cmd4.ExecuteReader();
Console.WriteLine("2nd attempt: " + reader2["text"]); //outputs correctly
conn.Close();

好吧,所以我关于在connection.Close()之后丢失更改的假设是不正确的。它肯定找到了新插入的行并将其输出到控制台。但是,在我停止应用程序后,表和行仍然消失。

Working with MonoTouch .NET for iPhone and SQLite on Mac OSX. I can read from the database no problem. However, when I attempt to make changes to the database, I get strange behavior. The code below runs without exception, but no real changes are being made to the database. I can create a table, insert a record, select that record, and display it in the console. But, when I close the db connection, all those changes go away. Further, if I put a break-point in the code before conn.Close() and check the database, the table doesn't exist. Sounds like I'm only working with an imaginary database that responds to actual SQL statements. Weird.

This code runs but does not actually write anything to the database:

const string _connectionString = "Data Source=App_Data/MyDatabaseFile";

var conn = new SqliteConnection(_connectionString);
conn.Open();

var command = conn.CreateCommand();

command.CommandText = "CREATE TABLE Test (id integer primary key AUTOINCREMENT, text varchar(100))";
command.ExecuteNonQuery();

var cmd2 = conn.CreateCommand();
cmd2.CommandText = "INSERT INTO Test (Text) Values ('test test test')";
var rowsAffected = cmd2.ExecuteNonQuery(); //rowsAffected is 1

var cmd3 = conn.CreateCommand();
cmd3.CommandText = "SELECT * FROM Test";
var reader = cmd3.ExecuteReader();
Console.WriteLine(reader["text"]); //writes "test test test" to console, nothing in database

conn.Close();

If I execute the same SQL statements in in SQLite Browser, they work fine:

CREATE TABLE Test (id integer primary key AUTOINCREMENT, text varchar(100));
INSERT INTO Test (Text) Values ('test test test');
SELECT * FROM Test;

... yields { id = 1, text = 'test test test' }

You can probably tell, but it's worth mentioning that I'm not using transactions.

UPDATE:

Interesting... I can change the code above that runs the SELECT query to look in 'Test2' (non-existent table) and it throws an SQLiteException: "No such table: Test2".

I also tried wrapping the above code in a transaction on the off chance that SQLite requires transactions... no dice.

UPDATE #2:

Adam suggested trying to open a new connection and SELECT from the new table again before stopping the application. I added the following code after the above code:

var conn2 = new SqliteConnection(_connectionString);
conn2.Open();
var cmd4 = conn2.CreateCommand();
cmd4.CommandText = "SELECT * FROM Test";
var reader2 = cmd4.ExecuteReader();
Console.WriteLine("2nd attempt: " + reader2["text"]); //outputs correctly
conn.Close();

Alright, so my assumption about it losing changes after connection.Close() is incorrect. It definitely found the newly inserted row and output it to the console. However, the table and row still disappear after I stop the application.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

a√萤火虫的光℡ 2024-09-19 01:57:28

对于任何处理同样问题的人,我想我应该继续发布我的发现。我在原来的帖子中描述的行为主要是设计使然。为了更清楚,这里有一个更好的解释:

当 MonoDevelop 将您的应用程序部署到 iPhone 模拟器时,您的 SQLite 数据库的副本会随之出现在 iPhone 环境中。因此,当您的应用程序修改数据库时,原始数据库不会被触及。当您的应用程序停止时,您对数据库的模拟器副本所做的更改将会丢失。但是,当应用程序运行时,您可以插入、更新、删除和选择您想要的所有内容,并且一切都应该按预期工作。

仅当使用模拟器时才如此。

For anyone dealing with the same question, I thought I'd go ahead and post my findings. The behavior I described in my original post is mostly by design. To be more clear, here's a better explanation:

When MonoDevelop deploys your app to the iPhone Simulator, a COPY of your SQLite database goes with it to live in the iPhone environment. So, when your app modifies your database, the original database isn't being touched. When your app stops, the changes you made to the simulator copy of your database are lost. However, while the app is running, you can insert, update, delete and select all you want and everything should work as expected.

This is only true when using the Simulator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文