MySQL 连接器/NET 开发人员指南  /  第 10 章连接器/NET FAQ

第 10 章连接器/NET FAQ

问题

  • 10.1: 事务开始后执行的所有命令是否自动登记在事务中?

  • 10.2: 如何获取自增列的值?

问题和解答

10.1: 事务开始后执行的所有命令是否自动登记在事务中?

是的。当客户端在经典 MySQL 中开始事务时,所有后续命令(在该连接上)都是该事务的一部分,直到客户端提交或回滚事务。要在该事务之外执行命令,您必须打开一个单独的连接。

10.2: 如何获取自增列的值?

使用时CommandBuilder,将 ReturnGeneratedIdentifiers属性设置为 true不再有效,因为 默认情况下CommandBuilder不添加 last_insert_id()

CommandBuilder 连接到 DataAdapter.RowUpdating事件处理程序,这意味着它会为每一行调用。它检查命令对象,如果它是相同的引用对象,它实际上会重建该对象,从而破坏命令文本更改。

解决此问题的一种方法是克隆命令对象,以便您拥有不同的实际引用:

dataAdapter.InsertCommand = cb.GetInsertCommand().Clone()

这可行,但由于 CommandBuilder 仍连接到 DataAdapter,因此 RowUpdating 事件仍会触发,从而对性能产生不利影响。要停止这种情况,添加所有命令后,您需要断开 CommandBuilder 与 DataAdapter 的连接:

cb.DataAdapter = null;

最后一个要求是确保id 返回的last_insert_id()具有正确的名称。例如:

SELECT last_insert_id() AS id

此处显示了一个完整的工作示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using MySql.Data;
using MySql.Data.MySqlClient;

namespace GetAutoIncId
{
    class Program
    {
        static void Main(string[] args)
        {
            string connStr = "server=localhost;user=root;database=TestDB;port=3306;password=******;";
            MySqlConnection conn = new MySqlConnection(connStr);

            try
            {
                Console.WriteLine("Connecting to MySQL...");
                conn.Open();

                string sql = "SELECT * FROM TestTable";

                MySqlDataAdapter da = new MySqlDataAdapter(sql, conn);
                MySqlCommandBuilder cb = new MySqlCommandBuilder(da);

                MySqlCommand cmd = new MySqlCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;
                // use Cloned object to avoid .NET rebuilding the object, and
                // thereby throwing away our command text additions.
                MySqlCommand insertCmd = cb.GetInsertCommand().Clone();
                insertCmd.CommandText = insertCmd.CommandText + ";SELECT last_insert_id() AS id";
                insertCmd.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
                da.InsertCommand = insertCmd;
                cb.DataAdapter = null; // Unhook RowUpdating event handler

                DataTable dt = new DataTable();
                da.Fill(dt);

                DataRow row = dt.NewRow();
                row["name"] = "Joe Smith";

                dt.Rows.Add(row);
                da.Update(dt);

                System.Console.WriteLine("ID after update: " + row["id"]);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            conn.Close();
            Console.WriteLine("Done.");
        }
    }
}