做人事档案的系统考虑到数据的安全性与一致性,毕竟是要对外上线、真正投入使用的项目,数据库的可靠性与安全性上我们开发人员要考虑的就很多了,记得做机房收费系统时注册新卡是自己为了简单,写成了一个存储过程(存储过程加事务),完成了一个功能的实现就万事大吉了,这次想换一种新的方法:经过和师哥的交流学习,在代码中使用事务同样也是可以解决问题的,可以保证数据的正确性,就像银行取款一样,如果在取款的过程中取款机出现故障,我们个人的账户上的金额不会受任何影响等。

代码中使用事务前提:务必保证一个功能(或用例)在同一个打开的数据连接上,放到同一个事务里面操作。

首先是在D层添加一个类为了保存当前操作的这一个连接放到一个事务中执行,并事务执行打开同一个连接、事务完成关闭同一个连接的一个共有类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Maticsoft.DBUtility;
namespace PersonalFiles.DAL
{
public class DBTransaction
{
private DbHelperSQL SqlHelper = null; public DBTransaction()
{
SqlHelper = new DbHelperSQL();
} /// <summary>
/// 获取数据库连接
/// </summary>
/// <returns></returns>
public SqlConnection GetConnection()
{
return SqlHelper.GetCon();
} /// <summary>
/// 获取事务
/// </summary>
/// <returns></returns>
public SqlTransaction GetTransaction(SqlConnection conn)
{
return conn.BeginTransaction();
} /// <summary>
/// 提交事务
/// </summary>
public void Commit(SqlTransaction sqlTransaction)
{
sqlTransaction.Commit();
} /// <summary>
/// 回滚事务
/// </summary>
public void Rollback(SqlTransaction sqlTransaction)
{
sqlTransaction.Rollback();
} /// <summary>
/// 关闭连接
/// </summary>
public void Close(SqlConnection conn)
{ if (conn.State == ConnectionState.Open)
{
conn.Close();
} }
}
}

界面层的后台代码和以前一样直接调去就行了,现在来看主要是在B层中的代码发生了很大的变化,需要向下层传递事务与获取的连接

/// <summary>
/// 增加一条数据
/// </summary>
public void Add(PersonalFiles.Model.BasicInformation modelBasic, PersonalFiles.Model.T_HumanAgency model)
{
int flag = 0; DBTransaction DbTran = new DBTransaction(); //获得连接
SqlConnection conn = DbTran.GetConnection(); //开启事务
SqlTransaction trans = DbTran.GetTransaction(conn);
try
{
//把获得的同一个连接与事务一共传下去
//dalBasic.Add(modelBasic,conn,trans); //把获得的同一个连接与事务一共传下去 dalAgency.Add(model,conn,trans); //事务提交
DbTran.Commit(trans);
//return true;
} catch (Exception ex)
{
//回滚事务
DbTran.Rollback(trans);
}
finally
{
DbTran.Close(conn);
}
}

注意的是向D层传是我们需要传的是B层获取的同一个连接于开启的是一个事务:

/// <summary>
/// 增加一条数据
/// </summary>
public void Add(PersonalFiles.Model.T_HumanAgency model,SqlConnection conn,SqlTransaction trans)
{
StringBuilder strSql = new StringBuilder();
strSql.Append("insert into T_HumanAgency(");
strSql.Append("myidentity,relation,receivemode,workingtime,intotime,oldworkplace,nowworkplace,inervice,registered,registeredcardid,registeredid,householder,isrecord,fileintotime,fileouttime,filetowhere,relationouttime,Paymentstandard,paymentsmonth,payments,stoptime,state,pri,admin,ID)");
strSql.Append(" values (");
strSql.Append("@myidentity,@relation,@receivemode,@workingtime,@intotime,@oldworkplace,@nowworkplace,@inervice,@registered,@registeredcardid,@registeredid,@householder,@isrecord,@fileintotime,@fileouttime,@filetowhere,@relationouttime,@Paymentstandard,@paymentsmonth,@payments,@stoptime,@state,@pri,@admin,@ID)");
SqlParameter[] parameters = {
new SqlParameter("@myidentity", SqlDbType.VarChar,50),
new SqlParameter("@relation", SqlDbType.VarChar,50),
new SqlParameter("@receivemode", SqlDbType.VarChar,50),
new SqlParameter("@workingtime", SqlDbType.VarChar,50),
new SqlParameter("@intotime", SqlDbType.VarChar,50),
new SqlParameter("@oldworkplace", SqlDbType.VarChar,50),
new SqlParameter("@nowworkplace", SqlDbType.VarChar,50),
new SqlParameter("@inervice", SqlDbType.VarChar,50),
new SqlParameter("@registered", SqlDbType.VarChar,50),
new SqlParameter("@registeredcardid", SqlDbType.VarChar,50),
new SqlParameter("@registeredid", SqlDbType.VarChar,50),
new SqlParameter("@householder", SqlDbType.VarChar,50),
new SqlParameter("@isrecord", SqlDbType.VarChar,50),
new SqlParameter("@fileintotime", SqlDbType.VarChar,50),
new SqlParameter("@fileouttime", SqlDbType.VarChar,50),
new SqlParameter("@filetowhere", SqlDbType.VarChar,50),
new SqlParameter("@relationouttime", SqlDbType.VarChar,50),
new SqlParameter("@Paymentstandard", SqlDbType.VarChar,50),
new SqlParameter("@paymentsmonth", SqlDbType.VarChar,50),
new SqlParameter("@payments", SqlDbType.VarChar,50),
new SqlParameter("@stoptime", SqlDbType.VarChar,50),
new SqlParameter("@state", SqlDbType.VarChar,50),
new SqlParameter("@admin", SqlDbType.VarChar,50),
new SqlParameter("@pri", SqlDbType.VarChar,50),
new SqlParameter("@ID", SqlDbType.VarChar,50)};
parameters[0].Value = model.myidentity;
parameters[1].Value = model.relation;
parameters[2].Value = model.receivemode;
parameters[3].Value = model.workingtime;
parameters[4].Value = model.intotime;
parameters[5].Value = model.oldworkplace;
parameters[6].Value = model.nowworkplace;
parameters[7].Value = model.inervice;
parameters[8].Value = model.registered;
parameters[9].Value = model.registeredcardid;
parameters[10].Value = model.registeredid;
parameters[11].Value = model.householder;
parameters[12].Value = model.isrecord;
parameters[13].Value = model.fileintotime;
parameters[14].Value = model.fileouttime;
parameters[15].Value = model.filetowhere;
parameters[16].Value = model.relationouttime;
parameters[17].Value = model.Paymentstandard;
parameters[18].Value = model.paymentsmonth;
parameters[19].Value = model.payments;
parameters[20].Value = model.stoptime;
parameters[21].Value = model.state;
parameters[22].Value = model.pri;
parameters[23].Value = model.admin;
parameters[24].Value = model.ID; //DbHelperSQL.ExecuteSql(strSql.ToString(), parameters);
DbHelperSQL.ExecuteSql(strSql.ToString(),conn,trans, parameters);
}

在代码中添加事务与存储过程中添加事务的异同

相同点

1:都能够保证数据的一致性。

不同点:

1:代码中添加事务的好处是:增加了代码的可读性、与可维护性,方便后期人员维护系统看代码能够一目了然的看懂代码,而在数据库中添加存储过程的可读性不是很好。

2:为什么不建议使用数据库自带的存储过程+事务呢?主要是一个项目过多的依赖数据库,这样对后期的数据库迁移都会带来一定的影响与不便(sql向oracle迁移),好多转换不是很容易兼容性和不是很好(以后再深入学习)。

3:合作开发时如果是代码中添加事务遵循了代码上传的原则,这样方便大家的交流。

为什么使用事务可以保证同一个连接向数据库多个表写信息的正确性与一致性的原理:

事务的原子性

事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据改操作要全部执行,要么全部不执行。这种特性称为原子性。  事务的原子性要求,如果把一个事务看作是一个程序,它要么完整的被执行,要么完全执行。就是说事务的操纵序列或者完全应用到数据库或者完全不影响数据库。这种特性称为原则性  假如用户在一个事务内完成了对数据库的更新,这时所有的更新对外部世界必须是可见的,或者完全没有更新。前者称事务已提交,后者称事务撤销。DBMS必须确保由成功提交的事物完成的所有操作在数据库内有完全的反映,而失败的事务对数据库完全没有影响

事务的隔离性

事务开始执行了但是没有提交事务,数据并没有真正的写到数据库里面,当我去断点测试的时候当第一个程序向数据库发出写完时,我去查找数据库不能打开数据库,不能查找,提示连接超时,由于事务的隔离性,数据并没有真正的写到数据库里面,等事务提交才可以查到数据库,可见同一个连接下执行的程序在同一个事务执行的开始于结束后才真正写到数据库里面,如果过程当中保存事务回滚,数据不会写到数据库里面。保证数据的一致性与正确性。

数据的准确性与一致性是我们要时刻考虑的,一个好的系统必须有较好的准确性才能保证用户的使用。

代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性的更多相关文章

  1. 在易语言中调用MS SQL SERVER数据库存储过程方法总结

    Microsoft SQL SERVER 数据库存储过程,根据其输入输出数据,笼统的可以分为以下几种情况或其组合:无输入,有一个或多个输入参数,无输出,直接返回(return)一个值,通过output ...

  2. Ado.Net实体数据模型EF,如何在代码中添加数据库连接密码

    在创建EF模型的时候,VS2013提示说“在连接字符串中存储敏感数据可能有安全风险”,于是我选择了在代码中添加,可是如何通过代码添加呢? 我在网上百度了下,没有人说的清楚直观. 假设我们创建了一个名字 ...

  3. 移动端网站如何开发(电脑端网站到手机端网站我们需要在html代码中添加哪个meta标签)

    移动端网站如何开发(电脑端网站到手机端网站我们需要在html代码中添加哪个meta标签) 一.总结 一句话总结: 添加viewport标签:meta name="viewport" ...

  4. MySQL--视图view、触发器trigger、事务(start transaction)、存储过程(特殊的数据逻辑处理函数)、流程控制(if,case....)

    mysql致力于项目开发及数据库管理之间解耦合(帮忙封装一些数据处理方法,使应用程序的开发者可以专注于应用程序的开发),但受限于不同部门沟通的成本问题,现阶段直接使用的价值不大. 一.视图(只能sel ...

  5. springmvc 事务控制与数据库隔离级别

    springmvc 事物传播与数据库隔离控制 http://www.cnblogs.com/yangy608/archive/2011/06/29/2093478.html 一.Propagation ...

  6. unity中添加音量控制的一些步骤

    1.先确认要控制的音源(Audio Source)所使用的输出(Output),例如我这里BGM使用的是MainMixer: 2.暴露音量(Volume)参数,让脚本可以控制.这里如果不暴露出来,脚本 ...

  7. (转)Unity3d使用心得(1):ModelImporter的使用、在代码中添加动画片段。

    在使用 Unity3d 倒入Fbx模型的时候,动画的动画片段需要自己手动添加模型多了以后会是一个不小的工作量. Unity3d支持 编辑器脚本来控制资源导入的过程.添加一个 AssetPostproc ...

  8. 如何优雅的在 vue 中添加权限控制

    前言 在一个项目中,一些功能会涉及到重要的数据管理,为了确保数据的安全,我们会在项目中加入权限来限制每个用户的操作.作为前端,我们要做的是配合后端给到的权限数据,做页面上的各种各样的限制. 需求 因为 ...

  9. 如何在 vue 中添加权限控制管理?---vue中文社区

    前言 在一个项目中,一些功能会涉及到重要的数据管理,为了确保数据的安全,我们会在项目中加入权限来限制每个用户的操作.作为前端,我们要做的是配合后端给到的权限数据,做页面上的各种各样的限制. 需求 因为 ...

随机推荐

  1. QJ系列笔记

    1.求int型数据在内存中存储时1的个数输入一个int型数据,计算出该int型数据在内存中存储时1的个数. #include<stdio.h> void main() { ; int yu ...

  2. 【Java 小实验】重写(覆写 Override)返回值类型能不能相同

    背景 每次看到重写那里写着: 重写机制是指子类的方法的方法名.参数表.返回值与父类中被重写的方法都相同,而方法体不同. 而重载是: 方法名与父类中的相同,而参数表不同,则属于同名方法的重载. 本来的感 ...

  3. Object.prototype.toString.call() 区分对象类型(判断对象类型)

    在 JavaScript 里使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种.对于数组. ...

  4. 本地/远程Service 和Activity 的交方式(转)

    android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remo ...

  5. poj1423---求一个大数的位数方法,我猜网站上统计输入字符少于多少位的那个算法

    法一:对一个数求它的对数,+1取整为其位数 问题转化为int (log10(N!)+1),对数性质log10(N!)=log10(N)+log10(N-1)+...+log10(1) /*用log10 ...

  6. 网易云课堂_程序设计入门-C语言_第四周:循环控制_1素数和

    1 素数和(5分) 题目内容: 我们认为2是第一个素数,3是第二个素数,5是第三个素数,依次类推. 现在,给定两个整数n和m,0<n<=m<=200,你的程序要计算第n个素数到第m个 ...

  7. 网易云课堂_程序设计入门-C语言_第四周:循环控制_2念整数

    2 念整数(5分) 题目内容: 你的程序要读入一个整数,范围是[-100000,100000].然后,用汉语拼音将这个整数的每一位输出出来. 如输入1234,则输出: yi er san si 注意, ...

  8. 得到当前网址的域名 ASP.NET

    HttpContext.Current.Request.Url.Host.ToString(); http://"是协议名 "www.test.com"是域名 " ...

  9. 学习Java这几个快捷键你得知道(不断更新中)

    java中的System.out.println();的快捷键    --------先输入sysout  在按 alt + /

  10. Java基础笔记-异常

    Java中的异常机制: Throwable类是 Java 语言中所有错误或异常的超类.主要包括两个子类: Error和Exception. 一般中要处理的异常是Exception. Java中最常见的 ...