跨数据库事务


/// <summary>
/// 多数据库服务器事务提交
/// </summary>
/// <param name="sqlStrings">key为connName,value为Sql语句</param>
/// <returns></returns>
public bool ExecuteMultiTran(List<string[]> sqlStrings)
{
bool reval = true;

SqlCommand cmd = new SqlCommand();
SqlTransaction tran;
SqlConnection conn;
//事务对象名,事务对象的集合
Dictionary<string, SqlTransaction> tranResult = new Dictionary<string, SqlTransaction>();

//conn对象名,对象
Dictionary<string, SqlConnection> connResult = new Dictionary<string, SqlConnection>();

//当前是否执行成功
bool isSuccess = true;

//
List<string> keys = new List<string>();

//通过connName进行循环执行事务
foreach (string[] sqls in sqlStrings)
{
string keyName = sqls[0];

//如果keys中已经存在当前 keyname,说明改conn的已经执行完毕,跳到下一keyname执行
if (!keys.Contains(keyName))
{
keys.Add(keyName);

//提交当前conn的事务,如果失败,标记当前事务失败
try
{
conn = CreateConnection(keyName);
conn.Open();
cmd.Connection = conn;
tran = conn.BeginTransaction();
cmd.Transaction = tran;

//记录当前事务
tranResult.Add(keyName, tran);

//记录当前conn
connResult.Add(keyName, conn);

//读取当前conn的sql,执行
foreach (string[] sql in sqlStrings)
{
if (sql[0] == keyName)
{
cmd.CommandText = sql[1];
cmd.ExecuteNonQuery();
}
}
}
catch(Exception ex)
{
isSuccess = false;
}

if (!isSuccess)
{
break;
}
}
}

//如果当前事务失败,把执行过的所有事务对象rollBack
if (!isSuccess)
{
foreach (SqlTransaction sqlTran in tranResult.Values)
{
sqlTran.Rollback();
}
reval = false;
}
else
{
foreach (SqlTransaction sqlTran in tranResult.Values)
{
sqlTran.Commit();
}
}
//关闭conn
foreach (SqlConnection value in connResult.Values)
{
if (value.State != ConnectionState.Closed)
{
value.Close();
}
}
return reval;
}

public SqlConnection CreateConnection(string keyName)
{
SqlConnection sqlconn = new SqlConnection(ConfigurationManager.AppSettings[keyName].ToString());
return sqlconn;
}

调用:


//1.扣减玩家拍币数
//2.增加玩家保险柜金豆数
//3.插入拍币兑换记录
private bool procData(int UserID, int pats, int ConvertRate, string ClientIP)
{
List<string[]> sqls = new List<string[]>();
//1.扣减玩家拍币数
string sql = "update AccountsInfo set UserPat=UserPat-" + pats + " where UserID=" + UserID;
sqls.Add(new string[] { "DBAccounts", sql });
//2.增加玩家保险柜金豆数
sql = "update GameScoreInfo set InsureScore=InsureScore+" + pats * ConvertRate + " where UserID=" + UserID;
sqls.Add(new string[] { "DBTreasure", sql });
//3.插入拍币兑换记录
sql = "insert into RecordConvertUserpat (RecordID,UserID,CurInsureScore,CurUserPat,ConvertUserPat,ConvertRate,IsGamePlaza,ClientIP,CollectDate) values(";
sql += ((int)gData.SelectValue("select max(RecordID) from RecordConvertUserpat", "DBRecord", 0) + 1) + ",";
sql += UserID + ",";
sql += gData.SelectValue("select InsureScore from GameScoreInfo where UserID=" + UserID, "DBTreasure", 0) + ",";
sql += gData.SelectValue("select UserPat from AccountsInfo where UserId=" + UserID, "DBAccounts", 0) + ",";
sql += pats + ",";
sql += ConvertRate + ",";
sql += "1,";
sql += "‘" + ClientIP + "‘,";
sql += "‘" + System.DateTime.Now.ToString() + "‘";
sql += ")";
sqls.Add(new string[] { "DBRecord", sql });

return gData.ExecuteMultiTran(sqls);
}

跨数据库事务,布布扣,bubuko.com

时间: 2024-10-05 09:25:05

跨数据库事务的相关文章

SQL Server 跨数据库事务

模拟三个库(同一个实例中),分别是DB1.DB2.DB3 整个事务的业务如下: 1.DB1写入表数据 2.DB2写入表数据 3.DB3调用存储过程写入表数据 4.每次写入表数据间隔模拟抛异常流程,查看数据是否回滚 代码如下: BEGIN TRY BEGIN TRAN INSERT INTO DB1.dbo.Log ( Type, Message, Stack, Created ) VALUES  ( 0, -- Type - int N'Message', -- Message - nvarch

『数据库』随手写了一个 跨数据库 数据迁移工具

随手写了一个 跨数据库 的 数据迁移工具:>目前支持 SQLServer,MySql,SQLite: >迁移工具 可以自动建表,且 保留 主键,自增列: >迁移工具 基于 Laura.Source  ORM框架 开发: >迁移工具 支持 崩溃恢复(重启迁移工具,将会继续 未完成的 数据迁移): >每张表一个事务(即使  表中有 >100W 的数据,也是一个事务完成): >迁移后 的 自增列 和 原数据库 保持一致: 只是展示一下,直接上图片: 操作工具: 迁移工具

【Java EE 学习第19天】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】

一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: (1)使用GZIPOutputStream工具对数据进行压缩,中间借助了ByteArrayOutputStream类进行结果的存储. (2)使用过滤器对浏览器请求进行拦截,通过自定义HttpServletResponse类(使用包装模式),重写getWriter方法,使得写出的目的地转变成ByteA

跨库事务一致性问题的解决方案(例)

我们看一个跨库事务一致性的问题,这是一个简单的场景:有新老两个系统,对应新老两套数据库,新数据库采用分库分表的设计,考虑到项目发布之后可能存在风险,采取了新老系统的并行方案.这个系统的业务比较简单:接收来自外部的数据,然后对数据进行核对处理.为了保证新老系统能够并行,在接收数据的时候必须实现双写方案,从而导致了跨库事务的一致性问题. 下面一幅图展示这一简单的场景 这里面会存在一个小问题,就是可能存在写入老库成功,但是写入新库失败的场景. 我们假设出现这种概率的情况是百万分之一,在系统发布的情况下

EF5.0中的跨数据库操作

以前在用MVC + EF 的项目中,都是一个数据库,一个DbContext,因此一直没有考虑过在MVC+EF的环境下对于多个数据库的操作问题.等到要使用时,才发现这个问题也不小(关键是有个坑).直接说这个问题的解决流程吧: 1)由以往的经验:在ADO.NET中,要操作多个数据库,那就多写两个SqlHelper吧,或封装下,能动态的修改链接字符串.因此想到在这里能不能建多个ADO.NET实体数据模型呢?于是乎就有了这样两个文件:SealDBModel.edmx及UcmsDBModel.edmx.

数据库事务的四大特性和事务隔离级别

Reference: [1] http://www.cnblogs.com/fjdingsd/p/5273008.html [2] http://blog.csdn.net/fg2006/article/details/6937413 数据库事务四大特性 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全

数据库事务隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复读.幻读这几类问题. √: 可能出现    ×: 不会出现   脏读 不可重复读 幻读 Read uncommitted √ √ √ Read committed × √ √ Repeatable read × × √ Serializable × × × 注意:我们讨论隔离级别的场景,主要是在多个

数据库-事务和锁

事务 所谓事务是用户定义的一个数据库操作系列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位.例如在关系数据库中,一个事务可以是一条sql语句.一组sql语句或整个程序. 给个栗子: 小IT在网上购物,其付款过程至少包括以下几步数据库操作: 更新客户所购商品的库存信息: 生成订单并且保存到数据库: 更新用户相关信息,例如购物数量等: 正常情况下,操作顺利进行,最终交易成功,那么与交易相关的所有数据库信息也成功更新.但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存

数据库事务的四大特性ACID

本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,所以事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响.为了实现原子性,需要通过日志:将所有对数据的更新操作都写入日志,如果一个事务中的一部分操作已经成功,但以后的操作,由于断电/系统崩溃/其它的软硬件错误而无法继续,则通过