2009-06-09 10 views
0

私はこのコードが問題ないと確信しています。私はあなたがinsertMediaTags関数(第2の関数)についてあなたが考えるものを知りたかったのです。私が心配しているのは、以下のコンカレントセーフです。もしinsertMediaTagsが十分に最適化されていれば?それは最初のfuncのためにトランザクションにあることに注意してくださいが、それはまた悪いことを意味するループにもありますか?このSQLコードは並行して安全ですか?

私は皆さんのコーディングの練習、スタイル、提案に自由に応えています。 (私はMySQLやMSのSQLまたは別のバージョンで使用するsqliteのATMが、そのプロトタイプのコードを使用しています、誰かが聞いてきます知っている)

{ 
     long mediaId; 
     //all the credentials should be verified by this point. 
     command.CommandText = "SELECT mediaId FROM media " + 
      "WHERE [email protected] AND [email protected];"; 
     command.Parameters.Add("@userId", DbType.Int64).Value = m.userid; 
     command.Parameters.Add("@title", DbType.String).Value = m.title; 
     if (command.ExecuteScalar() != null) 
      throw new System.InvalidOperationException("Title already exisit"); 

     using (var dbTrans = connection.BeginTransaction()) 
     { 
      command.CommandText = 
       "INSERT INTO " + 
       "media (userid, catagory, creation_date, current_media_date, current_desc_date, licence, title, desc, ext) " + 
       "VALUES(@userid, @catagory, @creation_date, @current_media_date, @current_desc_date, @licence, @title, @desc, @ext); " + 
       "SELECT last_insert_rowid() AS RecordID;"; 

      DateTime currentDate = m.creation_date; 
      command.Parameters.Add("@userid", DbType.Int64).Value = m.userid; 
      command.Parameters.Add("@catagory", DbType.Int64).Value = m.catagory; 
      command.Parameters.Add("@creation_date", DbType.DateTime).Value = m.creation_date; 
      command.Parameters.Add("@current_media_date", DbType.DateTime).Value = currentDate; 
      command.Parameters.Add("@current_desc_date", DbType.DateTime).Value = currentDate; 
      command.Parameters.Add("@licence", DbType.Int64).Value = m.license; 
      command.Parameters.Add("@title", DbType.String).Value = m.title; 
      command.Parameters.Add("@desc", DbType.String).Value = m.desc; 
      command.Parameters.Add("@ext", DbType.Int64).Value = m.ext; 

      mediaId = (long)command.ExecuteScalar(); 
      //m.collaborateWith 
      insertInspired(inspireLinks.external, inspireLinks.internalPair, mediaId); 
      insertDerived(deriveLinks.external, deriveLinks.internalPair, mediaId); 
      insertMediaTags(m.listTagString, mediaId); 
      //command.CommandText = "END TRANSACTION;";   command.ExecuteNonQuery(); 

      updateMediaForWatchers(m.userid, mediaId, m.catagory, currentDate); 
      dbTrans.Commit(); 
     } 
     return mediaId; 
    } 

    void insertMediaTags(List<string> tags, long mediaId) 
    { 
     foreach(string tag in tags) 
     { 
      //assure tag exist 
      long tagId; 
      command.CommandText = "SELECT tagid FROM tag_name WHERE [email protected];"; 
      command.Parameters.Add("@title", DbType.String).Value = tag; 
      object o = command.ExecuteScalar(); 
      if (o == null) 
      { 
       command.CommandText = 
        "INSERT INTO tag_name(title) VALUES(@title); " + 
        "SELECT last_insert_rowid() AS RecordID;"; 
       command.Parameters.Add("@title", DbType.String).Value = tag; 
       tagId = (long)command.ExecuteScalar(); 
      } 
      else 
       tagId = (long)o; 

      command.CommandText = 
       "INSERT INTO media_tags(mediaId, tagid) " + 
       "VALUES(@mediaId, @tagid);"; 
      command.Parameters.Add("@mediaId", DbType.Int64).Value = mediaId; 
      command.Parameters.Add("@tagid", DbType.Int64).Value = tagId; 
      command.ExecuteNonQuery(); 

      command.CommandText = 
       "UPDATE tag_name SET count = count+1 "+ 
       "WHERE [email protected]"; 
      command.Parameters.Add("@tagid", DbType.Int64).Value = tagId; 
      command.ExecuteNonQuery(); 
     } 
    } 
+0

SQLiteは現在のところ、並行処理をサポートしていません。 – SingleNegationElimination

+0

どのようにあなたがそれをキャッチしたのか分かりませんが、プロトタイプの部分を見逃して、私は別のフォームのSQLを使用するよ –

答えて

4

ありません、それは安全で併存ていません。タグが存在するかどうかを判断するためのSELECTと、存在しない場合はタグを作成するINSERTとの間で競合する可能性があります。スレッドAがSELECTを実行し、存在しないと判断した場合、スレッドAはINSERTを実行する前にスレッドBが同じ処理を行うとします。スレッドBも挿入を試み、失敗します。

+0

私にそれをビート;) –

+0

別の言い方をすると、SELECTクエリは、 。 –

+0

insertMediaTagsは、最初のメソッドでのみ呼び出されます。それにはトランザクションがあります。これはまだ問題ですか? (私はinsertMediaTagsにコメントをつけましたが、これはトランザクション内で常に呼び出さなければならないと言っています) - acidzombie24 0秒前[このコメントを削除] –

0

SQL Serverでは、SCOPE_IDENTITY()関数を使用することをお勧めします。それ以外は問題は見えません。

関連する問題