C# SQLite 事务 - 此用法是否有效



我已经开始涉足 C#,并且正在编写一段代码来处理将两个表插入我的 SQLite 数据库,并且仅在相关平台尚不存在时才插入"平台"的行。

代码按预期工作,但我正在寻求验证我是否正确处理交易。

也希望对任何看起来时髦或可以改进的东西有任何指示。

谢谢

private static string databaseFilePath = @"Data";
private static string databaseFileName = "myDB.db";
private static string databaseFullPath = String.Concat(databaseFilePath, databaseFileName);
private static string platformTableName = "Platforms";
private static string gameTableName = "Games";
// Create our tables
private async void CreateTables(SQLiteConnection connection, SQLiteTransaction transaction)
{
    // SQLite query string to create the Platform table
    string createPlatformTableQuery = @"CREATE TABLE IF NOT EXISTS [" + platformTableName + @"] (
        [Id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        [Name] TEXT NOT NULL,
        [ShortCode] TEXT NOT NULL,
        [Description] TEXT NOT NULL,
        [ReleaseDate] TEXT NOT NULL,
        [Images] TEXT NOT NULL,
        [Video] TEXT NOT NULL,
        [RomPaths] TEXT NOT NULL
    )";
    // SQLite query string to create the Games table
    string createGamesTableQuery = @"CREATE TABLE IF NOT EXISTS [" + gameTableName + @"] (
        [Id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        [Platform] TEXT NOT NULL,
        [Name] TEXT NOT NULL,
        [Crc] TEXT NOT NULL,
        [Screenshots] TEXT NOT NULL,
        [FanArt] TEXT NOT NULL,
        [BoxArt] TEXT NOT NULL,
        [CartArt] TEXT NOT NULL,
        [DiscArt] TEXT NOT NULL,
        [Music] TEXT NOT NULL,
        [Video] TEXT NOT NULL,
        [Players] INTEGER NOT NULL,
        [Description] TEXT NOT NULL,
        [ReleaseDate] TEXT NOT NULL,
        [Publisher] TEXT NOT NULL,
        [Developer] TEXT NOT NULL,
        [Rating] TEXT NOT NULL,
        [PlayCount] INTEGER NOT NULL,
        [PlayTime] REAL NOT NULL,
        [FilePath] TEXT NOT NULL
    )";
    // Create an SQLite command
    using (SQLiteCommand command = new SQLiteCommand(connection))
    {
        try
        {
            // Set the command to create our platform table
            command.CommandText = createPlatformTableQuery;
            // Execute the query
            await command.ExecuteNonQueryAsync();
            // Set the command to create our games table
            command.CommandText = createGamesTableQuery;
            // Execute the query
            await command.ExecuteNonQueryAsync();
        }
        // We encountered an exception
        catch (SQLiteException e)
        {
            // Rollback the transaction
            transaction.Rollback();
            // Throw the exception
            throw e;
        }
    }
}
// Insert Platforms (defined in PlatformList.cs) into the platforms table
private async void InsertPlatforms(SQLiteConnection connection, SQLiteTransaction transaction, PlatformList platformList)
{
    // Is this a fresh population of the Platforms table data?
    bool freshPopulation = false;
    // Create an SQLite command
    using (SQLiteCommand command = new SQLiteCommand(connection))
    {
        try
        {
            command.CommandText = "SELECT COUNT(*) from " + platformTableName;
            var count = await command.ExecuteScalarAsync();
            freshPopulation = Convert.ToInt16(count) <= 0;
        }
        // We encountered an exception
        catch (SQLiteException e)
        {
            // Rollback the transaction
            transaction.Rollback();
            // Throw the exception
            throw e;
        }
    }
    // Loop through the platform list
    foreach (var item in platformList.list)
    {
        // Populate an array from all items in each platformList entry
        string[] values = new string[]
        {
            item.name, item.shortCode, item.description, item.releaseDate, item.images, item.video
        };
        // Comma quote the values
        string commaQuotedValues = "'" + String.Join("','", values) + "'";
        string commandText = String.Concat("INSERT INTO ", platformTableName, " (Name, ShortCode, Description, ReleaseDate, Images, Video) Values (", commaQuotedValues, ")");
        // Create an SQLite command
        using (SQLiteCommand command = new SQLiteCommand(connection))
        {
            try
            {
                // If this is the first time we are inserting data into the platforms table
                if (freshPopulation)
                {
                    // Set the command text
                    command.CommandText = commandText;
                    // Execute the query
                    await command.ExecuteNonQueryAsync();
                }
                // There is already data in the platforms table.. Let's ensure that it's up to date
                else
                {
                    // Set the command to select an existing row from the platforms table (if it exists)
                    command.CommandText = @"SELECT ShortCode FROM " + platformTableName + " WHERE ShortCode='" + item.shortCode + "'";
                    // Start the data reader
                    using (SQLiteDataReader reader = command.ExecuteReader())
                    {
                        // If this row isn't already inserted into the database
                        if (!reader.HasRows)
                        {
                            // Insert any rows not already inserted into the platforms table
                            using (SQLiteCommand insertCommand = new SQLiteCommand(connection))
                            {
                                try
                                {
                                    // Set the command text
                                    insertCommand.CommandText = commandText;
                                    // Execute the query
                                    await insertCommand.ExecuteNonQueryAsync();
                                }
                                // We encountered an exception
                                catch (SQLiteException e)
                                {
                                    // Rollback the transaction
                                    transaction.Rollback();
                                    // Throw the exception
                                    throw e;
                                }
                            }
                        }
                    }
                }
            }
            // We encountered an exception
            catch (SQLiteException e)
            {
                // Rollback the transaction
                transaction.Rollback();
                // Throw the exception
                throw e;
            }
        }
    }
}
// Init
public async void Init()
{
    // Create an instance of the platform list
    PlatformList platformList = new PlatformList();
    // If the database doesn't exist
    if (!File.Exists(databaseFullPath))
    {
        // Create the database
        SQLiteConnection.CreateFile(databaseFullPath);
    }
    // Create an SQLite connection to the database
    using (SQLiteConnection connection = new SQLiteConnection(@"data source=" + databaseFullPath))
    {
        // Open the connection to the database
        await connection.OpenAsync();
        // Start a transaction
        using (SQLiteTransaction transaction = connection.BeginTransaction())
        {
            // Create the required tables
            CreateTables(connection, transaction);
            // Insert platforms into the Platforms table
            InsertPlatforms(connection, transaction, platformList);
            // Commit the transaction
            transaction.Commit();
        }
    }
}

如果代码由于任何异常而中止,则事务未完成;不应将回滚限制为 SQLiteException 秒。

若要重新引发当前异常,应使用 throw; 而不指定异常对象;否则,将重置异常信息(堆栈跟踪等(。

在 SQLite 中,一个连接只能有一个事务,因此您无需告诉命令对象要使用哪个事务(对于其他数据库,这可能有所不同(。

要回滚事务,您只需要一个 try/catch ,这应该在您创建事务的位置完成(删除所有其他catch es(:

using (var transaction = connection.BeginTransaction())
{
    try
    {
        CreateTables(connection);
        InsertPlatforms(connection, platformList);
    }
    catch (Exception e)
    {
        transaction.Rollback();
        throw;
    }
    transaction.Commit();
}

最新更新