C# 我需要在MySQL中使用事务对象吗

C# 我需要在MySQL中使用事务对象吗,c#,mysql,transactions,mono,C#,Mysql,Transactions,Mono,我需要创建一个MySQL表,并用Mono中的一些数据填充它。我正在使用以下代码执行此操作: public class TestModel { protected IDbConnection dbcon; public TestModel() { string connectionString = "Server=localhost;" + "Database=cikdata;"

我需要创建一个MySQL表,并用Mono中的一些数据填充它。我正在使用以下代码执行此操作:

public class TestModel
{
    protected IDbConnection dbcon;

    public TestModel()
    {
        string connectionString = "Server=localhost;"
                                + "Database=cikdata;"
                                + "User ID=root;"
                                + "Password=password;"
                                + "Pooling=false";
        dbcon = new MySqlConnection(connectionString);
        dbcon.Open();

        IDbCommand dbcmd = dbcon.CreateCommand();

        // Create table
        dbcmd.CommandText = "CREATE TABLE employee (firstname varchar(32), lastname varchar(32))";
        dbcmd.ExecuteScalar();

        // fill this table with some data

        dbcmd.CommandText = "SELECT firstname, lastname FROM employee";
        IDataReader reader = dbcmd.ExecuteReader();
        while(reader.Read()) {
            string FirstName = (string) reader["firstname"];
            string LastName = (string) reader["lastname"];
            Console.WriteLine("Name: " + FirstName + " " + LastName);
        }

        // clean up
        reader.Close();
        reader = null;

        dbcmd.Dispose();
        dbcmd = null;
    }

    ~TestModel()
    {
        dbcon.Close();
        dbcon = null;
    }
}
我已经看到了很多在Mono中使用MySQL的例子,其中使用了
IDbTransaction
。上面的代码在没有任何事务对象的情况下工作。我真的需要在代码中使用事务对象(和
IDbTransaction.Commit
)吗


很抱歉问了这么一个新手问题。我主要是一名C++/PHP开发人员,对C#和Mono几乎没有经验。

当您以一组单独的sql命令运行一个操作时,事务是一个好习惯

在这种情况下,这将取决于如果填充代码失败,是否希望回滚创建表

因此,您可以将其视为以下步骤

Start a transaction
Create the table
Insert some data
Commit transaction
如果没有显式事务,则存在不合法事务,因此如果在create table语句中附加一些insert语句,并调用ExcuteScalar,则会得到相同的效果

当您不想更改任何内容(如果其中任何部分失败)时,基本上使用启动事务/提交事务


或者,在执行“批处理”操作时,您不希望任何其他用户更改任何内容。

当您以一组单独的sql命令运行一个操作时,事务是一个好习惯

在这种情况下,这将取决于如果填充代码失败,是否希望回滚创建表

因此,您可以将其视为以下步骤

Start a transaction
Create the table
Insert some data
Commit transaction
如果没有显式事务,则存在不合法事务,因此如果在create table语句中附加一些insert语句,并调用ExcuteScalar,则会得到相同的效果

当您不想更改任何内容(如果其中任何部分失败)时,基本上使用启动事务/提交事务


或者,在执行“批处理”操作时,您不希望任何其他用户更改任何内容。

您绝对不应将该代码包含在事务中。如果你这样做,你只会让你自己或其他的代码读者感到困惑

这种情况下的原因是,
CREATE TABLE
在MySQL中导致了一个错误,因此在第一个命令(
CREATE TABLE
)之后,您将已经提交了事务,其余的命令将在事务之外执行。而回滚或提交不会做任何事情

如果您尝试回滚
创建表

mysql [localhost] {msandbox} (test) > start transaction;
Query OK, 0 rows affected (0.01 sec)

mysql [localhost] {msandbox} (test) > create table transtest(id int);
Query OK, 0 rows affected (0.32 sec)

mysql [localhost] {msandbox} (test) > rollback;
Query OK, 0 rows affected (0.02 sec)

mysql [localhost] {msandbox} (test) > select * from transtest;
Empty set (0.00 sec)

请注意,该表仍然存在……

您绝对不应该在事务中包含该代码。如果你这样做,你只会让你自己或其他的代码读者感到困惑

这种情况下的原因是,
CREATE TABLE
在MySQL中导致了一个错误,因此在第一个命令(
CREATE TABLE
)之后,您将已经提交了事务,其余的命令将在事务之外执行。而回滚或提交不会做任何事情

如果您尝试回滚
创建表

mysql [localhost] {msandbox} (test) > start transaction;
Query OK, 0 rows affected (0.01 sec)

mysql [localhost] {msandbox} (test) > create table transtest(id int);
Query OK, 0 rows affected (0.32 sec)

mysql [localhost] {msandbox} (test) > rollback;
Query OK, 0 rows affected (0.02 sec)

mysql [localhost] {msandbox} (test) > select * from transtest;
Empty set (0.00 sec)


注意桌子是怎么还在那里的…

理论上你是对的。然而,在MySQL中,CREATE TABLE永远不能在事务中,所以如果执行回滚操作,仍然会创建该表。我认为ExecuteScalar也是如此,因为在同一个事务中,没有任何东西可以围绕创建表和其他内容。我对此感到好奇,但更关心的是解释事务,而不是深入细节,也远离嵌套事务。MySQL没有嵌套事务:)不知道,尽管我不能说我感到惊讶,嵌套事务最大的效用是在复杂的存储过程中。理论上你是对的。然而,在MySQL中,CREATE TABLE永远不能在事务中,所以如果执行回滚操作,仍然会创建该表。我认为ExecuteScalar也是如此,因为在同一个事务中,没有任何东西可以围绕创建表和其他内容。我对此感到好奇,但更关心的是解释事务,而不是深入细节,也远离嵌套事务。MySQL没有嵌套事务:)不知道,尽管我不能说我感到惊讶,嵌套事务最大的实用程序是在复杂的存储过程中。所以我只需要在向表中插入一些数据时使用事务对象,对吗?这样,如果出现问题,我将能够回滚事务中的操作。如果您以“全部或无”为单位同时执行两个或多个insert/update/delete操作,则将其放入事务中。因此,只有在将某些数据插入表中时,我才需要使用事务对象,对吗?这样,如果出现问题,我将能够回滚事务中的操作。如果您以“全部或无”为单位同时执行两个或多个插入/更新/删除操作,则将其放入事务中。将IDisposable对象包装在“使用”块中,正如前面所说的,终结器在这里是个坏主意。谢谢,@skolima。我已经意识到为什么它如此糟糕。另外,当
TestModel
对象尚未删除时,是否需要保持与数据库的持久连接?对于特定的数据库查询/事务,
打开
&
关闭
连接可能会更好?打开新连接是一项代价高昂的操作,因此通常最好保留它,直到您真的不再需要它。将IDisposable对象包装在“使用”块中,正如前面所说的,终结器在这里是个坏主意。谢谢,@skolima。我已经意识到为什么它如此糟糕。另外,当
TestModel
对象尚未删除时,是否需要保持与数据库的持久连接?对于特定的数据库查询/事务,
打开
&
关闭
连接可能会更好?打开新连接是一项代价高昂的操作,因此通常最好保留它,直到您真正不再需要它。