博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF6学习笔记二十四:事务
阅读量:4542 次
发布时间:2019-06-08

本文共 4758 字,大约阅读时间需要 15 分钟。

要专业系统地学习EF推荐《你必须掌握的Entity Framework 6.x与Core 2.0》。这本书作者(汪鹏,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/

了解一下EF中事务。首先复习一下原始的SQL语句创建事务,然后也复习一下ADO中事务的使用。工作一年多我就没写过事务,因为用的是EF,事务就只是在学校中写过。

详细学习事务:  

begin transactionbegin try     insert into tb_Students values(newid(),'小明','44','2012-1-1');     insert into tb_Teachers values(newid(),'张四海','语文','2018-2-2');end trybegin catch    select ERROR_NUMBER() as ErrorNumber,  --  错误代码                ERROR_SEVERITY() as ErrorSeverity,-- 错误严重级别,级别小于10,try catch捕获不到                ERROR_STATE() as ErrorState, -- 错误状态码                ERROR_PROCEDURE() as ErrorProcedure,  --  出现错误的存储过程或触发器的名称                ERROR_LINE() as ErrorLine,  --  发生错误的行号                ERROR_MESSAGE() as ErrorMessage  --  错误的具体信息    if(@@TRANCOUNT > 0)  --  事务开启此值+1,判断是否开启事务          rollback transactionend catchif(@@TRANCOUNT > 0)commit tran
View Code
//  ado中使用事务string connStr = @"Data Source=LAPTOP-G81QJ856\SQLEXPRESS;Initial Catalog=_20190130.EFDbContext;Integrated Security=True";using (SqlConnection conn = new SqlConnection(connStr)){    Console.WriteLine(conn.State);  //  closed  我还以为使用using自动打开的    conn.Open();    string sql = @"insert into tb_Students values(newid(),'小强','44','2012-1-1');insert into tb_Teachers values(newid(),'张抛','数学','1999-9-2');";    using (SqlCommand cmd = new SqlCommand(sql, conn))    {        using (SqlTransaction tran = conn.BeginTransaction())        {            try            {                //  如果不告诉cmd使用哪个事务会报错                ////  System.InvalidOperationException: 如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有 事务。命令的 Transaction 属性尚未初始化。                cmd.Transaction = tran;                 var i = cmd.ExecuteNonQuery();                tran.Commit();            }            catch (Exception e)            {                tran.Rollback();                throw e;              }        }    }}
View Code

现在来看看EF中事务是怎么回事

我们平时在执行添加、修改、删除调用SaveChanges方法时,这些操作默认就会被事务包裹。查询操作则没有。

ctx.Students.Add(new Student { Name = "小刘", Score = "55", AddTime = DateTime.Now });
View Code

 当我们多次调用SaveChanges时,就会开启多个事务。

ctx.Students.Add(new Student { Name="小新",Score="66"});ctx.SaveChanges();ctx.Teachers.Add(new Teacher { Name="胡飘",Subject="历史"});ctx.SaveChanges();
View Code

现在来看EF中的一个关于事务的开关

public class EFDbContext : DbContext    {        public EFDbContext()        {            //此标志确定在使用此类方法时是否启动新事务            Configuration.EnsureTransactionsForFunctionsAndCommands = false;        }}
View Code

这个就是开启关闭事务的开关,但是他对SaveChanges是不起作用的,目前我只知道调用ExecuteSqlCommand方式时才有用。MSDN上对这个说的很简陋

那么看看EF中对这个属性的注释

还是直接使用它来看看。下面这条语句我关闭事务, 添加一条记录,然后调用SaveChanges,但其实,还是会开启事务

//  还是会有事务的            ctx.Configuration.EnsureTransactionsForFunctionsAndCommands = false;ctx.Database.Log = msg => Console.WriteLine(msg);ctx.Teachers.Add(new Teacher { Name = "胡愤", Subject = "历史" });ctx.Students.Add(new Student { Name = "小赵", Score = "66", AddTime = DateTime.MinValue });ctx.SaveChanges();
View Code

ExecuteSqlCommand也是默认被事务包裹,但是他就可以通过传递参数来实现事务的开启和关闭。

ctx.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, @"insert into tb_students values(newid(),'小刘','70',getdate())");
View Code

行吧,就是这样。

如果说我们想用ADO中那种方式来使用事务呢?当然是可以的,上下文提供了BeginTransaction,和ADO中的命名是一样的。

using (var transaction = ctx.Database.BeginTransaction()){    ctx.Teachers.Add(new Teacher { Name = "胡愤", Subject = "历史" });    ctx.SaveChanges();    ctx.Students.Add(new Student { Name = "小赵", Score = "66", AddTime = DateTime.Now });    ctx.SaveChanges();    transaction.Commit();}
View Code

 我虽然调用了两次saveChanges,但只有一个事务,但是必须要调用一次SaveChanges才能成功插入

最后开看一下EF提供的UseTransaction方法,这个是什么意思呢?允许上下文参与到已存在的事务中。

我们现在使用ADO,将ADO的transaction对象传递给EF的UseTransaction,那么我在ADO中的操作和在EF中的操作就可以处在同一个事务中

string connStr = @"Data Source=LAPTOP-G81QJ856\SQLEXPRESS;Initial Catalog=_20190130.EFDbContext;Integrated Security=True";using (SqlConnection conn = new SqlConnection(connStr)){    conn.Open();    string sql = @"insert into tb_students values(newid(),'小蓝 ','70',getdate())";    using (SqlCommand cmd = new SqlCommand(sql, conn))    {        using (SqlTransaction tran = conn.BeginTransaction())        {            try            {                cmd.Transaction = tran;                var i = cmd.ExecuteNonQuery();                using (EFDbContext ctx = new EFDbContext(conn))                {                    ctx.Database.UseTransaction(tran);                    ctx.Students.Add(new Student { Name = "小红", Score = "55", AddTime = DateTime.Now });                    ctx.SaveChanges();                }                tran.Commit();            }            catch (Exception e)            {                tran.Rollback();                throw e;            }        }    }}
View Code

 

 行吧,EF中简单的事务就到这里了。

 

转载于:https://www.cnblogs.com/jinshan-go/p/10339589.html

你可能感兴趣的文章
PAT甲级——A1054 The Dominant Color
查看>>
PAT甲级——A1075 PAT Judge
查看>>
PAT甲级——A1056 Mice and Rice
查看>>
PAT甲级——A1080 Graduate Admission
查看>>
PAT甲级——A1060 Are They Equal
查看>>
程序编译
查看>>
Python监听键盘和鼠标事件
查看>>
#141 Linked list cycle
查看>>
Asp.Net Mvc项目添加WebApi
查看>>
三级联动
查看>>
(Delphi)第一个Windows 32 API的窗口程序
查看>>
在Ubuntu16.04里面安装Gogland!
查看>>
ClamAV学习【7】——病毒库文件格式学习
查看>>
[LeetCode] Reverse Nodes in k-Group
查看>>
[LeetCode] Search in Rotated Sorted Array II
查看>>
[STL] lower_bound和upper_bound
查看>>
表单属性enctype="multipart/form-data"
查看>>
数值分析清考给弄纠结了
查看>>
转:GestureDetector: GestureDetector 基本使用
查看>>
小顶堆第二弹-----堆降序排序(C语言非递归)
查看>>