2011-09-16 23 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行为。