2011-09-16 49 views
2

我有一個類,它執行存儲在YAML文件中的SQL語句(更新,插入和刪除)。我希望所有的陳述都是一個交易的一部分。如果任何SQL語句失敗,則會回滾它們。如果所有的陳述都成功了,那麼他們會承諾。我正在連接到一個MySQL數據庫。這裏是我的代碼:如何在Ruby DataMapper中使用事務?

require 'dm-core' 

class SqlExecuter 

    def initialize(input_yaml_file_name) 
    @input_yaml_file_name = input_yaml_file_name 
    @adapter = DataMapper.repository(:default).adapter 
    @sql_statements = YAML::load(File.open(input_yaml_file_name)) 
    end 

    def execute() 
    puts "Executing SQL statements in #{@input_yaml_file_name} file...." 

    @sql_statements.each do | sql_statement | 
     @adapter.execute(sql_statement) 
    end 
    end 
end # class SqlExecuter 

我想我所有的@ adapter.execute調用是一個事務的一部分。我查看了dm-transactions gem中的代碼,但我無法弄清楚在這種情況下如何使用它。

+2

難道只是我,還是根本沒有'dm-transactions'的文檔?我當然找不到它。 – fennec

回答

5

使用,如果發生錯誤,這體現在交易和回滾SQL語句:

require 'dm-transactions' 
YourModel.transaction do |t| 
    begin 
    @sql_statements.each do |sql_statement| 
     DataMapper.repository(:default).adapter.execute(sql_statement) 
    end 
    rescue DataObjects::Error 
    t.rollback 
    end 
end 

Using transactions with Ruby DataMapper看一看,dm-transactions_spec.rb

+0

只要我的任意SQL語句涉及與YourModel有關係的表,上述內容就適用於我。謝謝。 – programmingfun11

0

林的原則,響應仍然是正確的。 User.transaction將在模型「User」所連接的存儲庫(數據庫)上打開一個事務。一個更通用的方法是

DataMapper.repository(:default).transaction do |t| 
    t.commit 
end 
+1

奇怪的是,我的sql_statements.each塊中的所有內容都被忽略。 '高清的execute()' '看跌期權 「執行中#SQL語句{@ input_yaml_file_name}文件.... \ n」' 'DataMapper.repository(:默認).transaction做| T |' 'begin' '@sql_statements.each do | sql_statement | '' 結果= @ adapter.execute(sql_statement)'' 結束'' rescue' 't.rollback' 'end' ''最終' 結束#execute' – programmingfun11

+1

你可能需要提交您的塊內交易:) – Xylakant

+0

我在塊內添加了t.commit,但@ sql_statements.each中的所有內容仍然被忽略。 – programmingfun11

4

據我所知,您不再需要調用rollback()一個事務回滾。你僅僅需要把它們放在一個事務塊,像這樣:

YourModel.transaction do 
    @sql_statements.each do |sql_statement| 
    DataMapper.repository(:default).adapter.execute(sql_statement) 
    end 
end 

至少,這就是我讀dm-transactions spec about rollbacks

it 'should rollback when an error is raised in a transaction' do 
    @user_model.all.size.should == 0 
    lambda { 
    @user_model.transaction do 
     @user_model.create(:name => 'carllerche') 
     raise 'I love coffee' 
    end 
    }.should raise_error('I love coffee') 
    @user_model.all.size.should == 0 
end 

我已經寫了使用帶有大量DataMapper的一個相當大的應用程序的交易和不使用rollback(),我所有的失敗事務總是回滾。

另外,從我記憶中的ActiveRecord(我已經使用AR了一年)開始,DataMapper事務行爲模仿AR行爲。