2017-02-05 12 views
1

私はC#でダブリングを開始しました。SQLiteデータベースに2つのテーブルを挿入し、問題のプラットフォームが存在しない場合は "Platforms"の行だけを挿入するためのコードセクションを作成しています。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(); 
     } 
    } 
} 

答えて

2

は、トランザクションが完了していないありがとう。ロールバックをSQLiteExceptionに制限しないでください。

現在の例外を再スローするには、例外オブジェクトを指定せずにthrow;を使用する必要があります。それ以外の場合は、例外情報(スタックトレースなど)がリセットされます。

SQLiteでは、接続には1つのトランザクションしかないので、コマンドオブジェクトに使用するトランザクションを指定する必要はありません(これは他のデータベースでは異なる場合があります)。トランザクションをロールバックする

は、あなただけの必要な単一トランザクション(他のすべてのcatch ESを削除)を作成する場所を実行する必要がありますtry/catch、:

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

ワンダフル、完全に理にかなっています。詳細な回答をありがとうございました – PersuitOfPerfection

関連する問題