首页 > 其他 > 详细

EF6学习笔记二十四:事务

时间:2019-01-30 20:23:20      阅读:140      评论:0      收藏:0      [点我收藏+]

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

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

详细学习事务:https://www.cnblogs.com/knowledgesea/p/3714417.html  

技术分享图片
begin transaction
begin try
     insert into tb_Students values(newid(),小明,44,2012-1-1);
     insert into tb_Teachers values(newid(),张四海,语文,2018-2-2);
end try
begin 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 transaction
end catch
if(@@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中简单的事务就到这里了。

 

EF6学习笔记二十四:事务

原文:https://www.cnblogs.com/jinshan-go/p/10339589.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!