2017-02-05 7 views
1

Ich habe begonnen, in C# zu dableiben und schreibe einen Codeabschnitt, um zwei Tabellen in meine SQLite-Datenbank einzufügen und Zeilen für "Plattformen" einzufügen, wenn die fragliche Plattform noch nicht existiert.C# SQLite-Transaktion - Ist diese Verwendung gültig?

Der Code funktioniert wie vorgesehen, aber ich suche Validierung, ob ich Transaktionen richtig handle.

Würde auch alle Hinweise auf etwas, das funky scheint oder könnte verbessert werden.

Danke

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(); 
     } 
    } 
} 

Antwort

2

Die Transaktion nicht abgeschlossen ist, wenn der Code aufgrund einer Ausnahme abgebrochen wird; Sie sollten den Rollback nicht auf SQLiteException s beschränken.

Um die aktuelle Ausnahme erneut zu werfen, sollten Sie throw; verwenden, ohne das Ausnahmeobjekt anzugeben; Andernfalls würden die Ausnahmeinformationen (Stack-Trace usw.) zurückgesetzt.

In SQLite kann eine Verbindung nur eine einzige Transaktion haben, sodass Sie den Befehlsobjekten nicht mitteilen müssen, welche Transaktion verwendet werden soll (dies kann bei anderen Datenbanken anders sein).

die Transaktion rückgängig zu machen, müssen Sie nur eine einzige try/catch, die getan werden sollte, in dem Sie die Transaktion (entfernen Sie alle anderen catch n) zu erstellen:

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

Wunderbar, die durchaus Sinn macht. Vielen Dank für die ausführliche Antwort – PersuitOfPerfection