2015-02-06 52 views
3

我正在使用mssql模塊連接到使用節點的sql server數據庫。藍鳥有一個類似於c#中資源管理的功能。它有一個'使用'方法來避免必須使用try/catch/finall來處理資源。他們有pg和mysql的例子,但是他們沒有mssql的例子,它不像pg和mysql那樣創建連接。這裏有一個如何使用它的一個例子:ms sql資源管理使用藍鳥承諾

using(getConnection(), 
    fs.readFileAsync("file.sql", "utf8"), function(connection, fileContents) { 
    return connection.query(fileContents); 
}).then(function() { 
    console.log("query successful and connection closed"); 
}); 

但是爲了能夠使用這種方法,你需要創建其中介紹瞭如何關閉連接的連接方法。這裏有一個例子爲PG:

function getSqlConnection(connectionString) { 
    var close; 
    return pg.connectAsync(connectionString).spread(function(client, done) { 
     close = done; 
     return client; 
    }).disposer(function(client) { 
     if (close) close(client); 
    }); 
} 

我與MSSQL模塊遇到的問題是,該連接方法不返回一個連接對象像皮克甚至mysql的模塊。有沒有人能夠用mssql做到這一點?

更新1:

這裏是我是如何做到的事務處理器:

function getTransaction(connection) { 
    return new Promise(function(resolve, reject) { 
     var tx = sql.Transaction(connection); 
     tx.beginAsync().then(function(err) { 
      if(err) { 
      tx = null; 
      return reject(err); 
      } 
      return resolve(tx); 
     }); 
    }).disposer(function(tx, promise) { 
     if(promise.isFulfilled()) { 
      return tx.commitAsync(); 
     } 
     else { 
      return tx.rollbackAsync(); 
     } 
    }); 
} 

這似乎是工作,但不知道這是否是有效的。現在我需要弄清楚如何在查詢中捕獲錯誤。

這就是我正在做一個交易:

using(getConnection(), function(connection) { 
    return using(getTransaction(connection), function(tx) { 
      return query(queryString, tx).then(function() { 
       console.log('first query in transaction completed.'); 
       console.log('starting second query in transaction.'); 
       return query(anotherQueryString, tx); 
      }); 
    }); 
}); 

如果我標記單個鉤掛到「使用」,將是捕獲所有的錯誤,從整個交易外?

回答

5

好問題,mssql真的很棘手的API(構造函數接受回調!),所以這是對文檔的很好的補充。

var Promise = require("bluebird"); 
var sql = Promise.promisifyAll(require("mssql")); 
global.using = Promise.using; 

function getConnection(config) { 
    var connection; 
    return new Promise(function(resolve, reject) 
     connection = new sql.Connection(config, function(err) { 
      if (err) { 
       connection = null; 
       return reject(err); 
      } 
      resolve(connection); 
     }); 
    }).disposer(function() { 
     if (connection) connection.close(); 
    }); 
} 

var config = { 
    user: '...', 
    password: '...', 
    server: 'localhost', 
    database: '...', 
}; 

using(getConnection(config), function(connection) { 
    var request = new sql.Request(connection); 
    return request.queryAsync("select 1 as number").then(function(recordSet) { 
     console.log("got record set", recordSet); 
     return request.queryAsync("select 10 as number"); 
    }); 
}).then(function(recordSet) { 
    console.log("got record set", recordSet); 
}) 

使用事務,嘗試實施getTransaction像:

function getTransaction(connection) { 
    var tx = new sql.Transaction(connection); 
    return tx.beginAsync().thenReturn(tx).disposer(function(tx, promise) { 
    return promise.isFulfilled() ? tx.commitAsync() : tx.rollbackAsync(); 
    }); 
} 

,並用它喜歡:

using(getConnection(), function(connection) { 
    return using(getTransaction(connection), function(tx) { 
    var request = new sql.Request(tx); 
    return request.queryAsync("INSERT 1...").then(function() { 
     return request.queryAsync("INSERT 2..."); 
    }).then(function() { 
     return request.queryAsync("INSERT 3..."); 
    }); 
    }); 
}); 

錯誤處理:

using(getConnection(), function(connection) { 
    return using(getTransaction(connection), function(tx) { 
    var request = new sql.Request(tx); 
    return request.queryAsync("INSERT..."); 
    }); 
}).catch(sql.TransactionError, function(e) { 
    console.log("transaction failed", e); 
}).catch(sql.ConnectionError, function(e) { 
    console.log("connection failed", e); 
}).catch(sql.RequestError, function(e) { 
    console.log("invalid query", e); 
}); 
+0

嗯,我會給那一槍。只是好奇你爲什麼promisifying所有mssql,但你不使用承諾?例如:你正在調用connection.close()而不是connection.closeAsync()。另外,你能告訴我一種在你的例子中集成交易的方法嗎?我可以看到「使用」聲明如何真正用於交易。 – u84six 2015-02-09 16:13:59

+1

@ u84six因爲'close'是一個同步方法 – Esailija 2015-02-09 16:19:14

+0

好吧,有點驚訝,因爲它是一個io操作。 – u84six 2015-02-09 16:22:41