c# - Different databases in one transaction -
i'm using transactionblock
code web application stores connection string in config.
until now, required write local db, , therefore, code worked. however, need data access method, write database using different connection string.
i've created new connection string in config file, i'm not sure how call , swap out.
the skeleton code have far is:
public class transactionblock : idisposable { private readonly bool _mfirsttransactionblock = false; private bool _mdisposed = false; public transactionblock(string connectionstringconfigkey = null) { if (connectionstringconfigkey != null && currenttransaction != null) throw new exception("can't create new transactionblock specific connectionstring if within block."); // open connection if haven't yet if (currenttransaction == null) // don't have transaction yet create one: { sqlconnection conn = new sqlconnection(connectionstring); // create new connection object connection string. try { conn.open(); } catch (sqlexception ex) { // severity 20 errors returned when there connection // problems, retry if severity 20. // don't worry deadlock errors in here - we're connecting // database, not running deadlocked. if (ex.class != 20) throw; // clear connection pool of connections related given connection string. sqlconnection.clearpool(conn); // try open connection once again, catching error. try { conn.open(); } catch { conn = null; } // if 2nd attempt failed, throw original exception. if (conn == null) throw; } currenttransaction = conn.begintransaction(); _mfirsttransactionblock = true; } } public void commit() { if (_mfirsttransactionblock) { dispose(true); } } public void dispose() { if (_mfirsttransactionblock) { dispose(false); } } private void dispose(bool commit) { if (_mdisposed) return; // committed , cleaned already. try { var transaction = currenttransaction; var connection = transaction.connection; // taking reference connection object rollback set null; if (commit) { transaction.commit(); } else // rollback transaction if hasn't been commited. { transaction.rollback(); } if (connection != null) { connection.close(); connection.dispose(); } transaction.dispose(); } // ensure regardless of connection exceptions, state set disposed. { // remove current transaction context. currenttransaction = null; _mdisposed = true; } } private static sqltransaction currenttransaction { { return currentcontext.getitem<sqltransaction>("__transaction"); } set { currentcontext.setitem("__transaction", value); } } public static sqlconnection connection { { return currenttransaction.connection; } } public static sqltransaction transaction { { return currenttransaction; } } private static string connectionstring; public static string connectionstring { { if (string.isnullorempty(connectionstring)) { try { connectionstring = configurationmanager.connectionstrings["defaultconnection"].connectionstring ?? ""; } catch (exception ex) { servicelogger.logerror("database: creating sql connection. can not find connection string. nothing work until resolved."); throw; } if (string.isnullorempty(connectionstring)) servicelogger.logerror("database: creating sql connection. can not find connection string. nothing work until resolved."); else servicelogger.loginfo(string.format("database: creating sql connection. connection string: {0}", connectionstring)); } return connectionstring; } } #region currentcontext helper class /// <summary> /// helper class easy access appropriate context containers. /// </summary> private static class currentcontext { public static t getitem<t>(string key) t : class { if (httpcontext.current != null) { return (t)httpcontext.current.items[key]; } else { return (t)callcontext.getdata(key); } } public static void setitem(string key, object value) { if (httpcontext.current != null) { httpcontext.current.items[key] = value; } else { callcontext.setdata(key, value); } } } #endregion /// <summary> /// adds application name connection string, if missing. /// </summary> /// <param name="connectionstring"></param> /// <returns>modified connection string</returns> private static string addapplicationnameifmissing(string connectionstring) { if (connectionstring == null) return null; // if connection string hasn't been configured application name, // add 1 (assumes application name not 1st element, unlikely have leading ';'). if (connectionstring.indexof(";application name=", stringcomparison.ordinalignorecase) >= 0) return connectionstring; // todo: if turns out slow perform on each query caching connection strings should added. // take site name if run website or webservice otherwise take process path. string appname = system.web.hosting.hostingenvironment.sitename ?? path.getfilenamewithoutextension(environment.getcommandlineargs()[0]); return connectionstring += string.format("{0}application name={1}", connectionstring.endswith(";") ? "" : ";", appname); } private interface istructuredparam { datatable todatatable(); } public sqlcommand createspcommand(string sql) { if (string.isnullorwhitespace(sql)) throw new argumentnullexception("sql"); sqltransaction tran = currenttransaction; if (tran == null) throw new nullreferenceexception("currenttransaction"); sqlconnection conn = tran.connection; if (conn == null) throw new nullreferenceexception("connection"); sqlcommand cmd = conn.createcommand(); if (cmd == null) throw new nullreferenceexception("command"); cmd.commandtext = sql; cmd.commandtype = commandtype.storedprocedure; cmd.transaction = tran; return cmd; } public void addparameter(sqlcommand cmd, string name, sqldbtype type, int size, object value, bool isoutput) { var p = cmd.createparameter(); p.parametername = name; p.sqldbtype = type; p.size = size; if (value == null) p.value = dbnull.value; else if (type == sqldbtype.structured) p.value = ((istructuredparam)value).todatatable(); else p.value = value; p.direction = isoutput == false ? parameterdirection.input : parameterdirection.output; cmd.parameters.add(p); } public void executeandmapreader(sqlcommand command, params action<idatareader>[] mappingmethods) { using (var reader = command.executereader()) { int = 0; { while (reader.read()) { if (reader.hasrows && mappingmethods != null && mappingmethods.any()) mappingmethods[i](reader); } i++; } while (reader.nextresult()); reader.close(); } } }
Comments
Post a Comment