栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

EntityFrameWork Core从零开始,(七)事务的应用与管理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

EntityFrameWork Core从零开始,(七)事务的应用与管理

前言:
数据库事务想必Web开发都十分的熟悉.
可以说是后台开发的必备技能了.
笔者在校招面试时,关于事务的问题就快要被问烂了
其无外乎
以下内容如不熟悉,请尽快复习
1.四大特性(ACID)
2.事务的传播属性
3.事务的隔离级别
4.Spring的声明式事务的原理(AOP)
5.一些具体的使用
(PS:分布式事务不在应届生事务问题之列…)

1.本地事务

EFCore的Savechanges()方法默认就是本地事务
及执行Savechanges()方法执行时会自动Commit,如果错误也能够自动进行回滚

当然,也可以手动控制本地事务

static void Main(string[] args)
{
    PPDbContext context = new PPDbContext();
    //在改数据库上下文中获取Transcation,
    var Transcation = context.Database.BeginTransaction();

    try
    {
        Person personOne = new Person();
        personOne.Name = 33;

        context.persons.Add(personOne);

        Pet petOne = new Pet();
        petOne.name = "mao1";
        petOne.owner = personOne;

        context.pets.Add(petOne);

        context.SaveChanges();
        //控制事务的提交
        Transcation.Commit();
    }
    catch(Exception e)
    {
    	//控制事务的回滚
        Transcation.Rollback();
    }

}

本地事务的功能有限,使用也比较简单.一般只需要注意事务失败的回滚即可

保存点(介绍)

EFCore在事务中引入了一种保存点的设置,
保存点是用来控制回滚的一种方式,及可以回滚到你设置的保存点(而不是把回滚到方法执行之前)
使用方式也很简单,这是两个API
详细用法参考:https://docs.microsoft.com/zh-cn/ef/core/saving/transactions

transcation.CreateSavePoint(String pointname)
transcation.RollbackToSavePoint(String pointname)
二.全局事务 1.跨多个数据库上下文的事务(多个DbContext参与事务)

前提:

  1. 必须是关系型数据库
  2. 必须共享同一个DbConnection(也就是说不可以跨数据库了)

要实现跨多个数据库上下文的事务也很简单,只需要稍微改一下数据库上下文的结构就行了

class PPDbContext:DbContext
{
   //将数据库连接改为由构造函数提供
   private DbConnection connection;
   public DbSet persons { get; set; }
   
   public DbSet pets { get; set; }
   //传入数据库连接
   public PPDbContext(DbConnection connection)
   {
       this.connection = connection;
   }

   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
       optionsBuilder.UseSqlServer(connection);
   }
}
static void Main(string[] args)
{
     DbConnection connection = new SqlConnection("server=X;Database=XXXX;uid=XX;pwd=XXXXX");
      //创建第一个数据库上下文
     PPDbContext context = new PPDbContext(connection);
      //获取数据库事务
     var Transcation = context.Database.BeginTransaction();

     try
     {
         Person personOne = new Person();
         personOne.Name = 33;

         context.persons.Add(personOne);

         Pet petOne = new Pet();
         petOne.name = "mao1";
         petOne.owner = personOne;

         context.pets.Add(petOne);

         context.SaveChanges();
          //创建第二个数据库上下文,为其设置同一个连接
          SOMDbcontext scontext = new SOMDbcontext(context.Database.GetDbConnection());
          //将上面创建的那个数据库事务传递给第二个数据库上下文
          scontext.Database.UseTransaction(Transcation.GetDbTransaction());
          
          
         Transcation.Commit();

     }
     catch(Exception e)
     {
         Transcation.Rollback();
     }

 }
2.不同的数据库访问技术共享事务

可以使用不同的数据库技术共享事务
此处由原例
ADO.NET 和EFCore共享事务(这个换个框架恐怕就不行了,毕竟这两都是微软官方的,且EFCore就是以ADO.NET为基础开发的)

using var connection = new SqlConnection(connectionString);
connection.Open();

using var transaction = connection.BeginTransaction();
try
{
    // Run raw ADO.NET command in the transaction
    var command = connection.CreateCommand();
    command.Transaction = transaction;
    command.CommandText = "DELETe FROM dbo.Blogs";
    command.ExecuteNonQuery();

    // Run an EF Core command in the transaction
    var options = new DbContextOptionsBuilder()
        .UseSqlServer(connection)
        .Options;

    using (var context = new BloggingContext(options))
    {
        context.Database.UseTransaction(transaction);
        context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
        context.SaveChanges();
    }

    // Commit transaction if all commands succeed, transaction will auto-rollback
    // when disposed if either commands fails
    transaction.Commit();
}
catch (Exception)
{
    // TODO: Handle failure
}
3.使用System.Transactions配置声明式事务(应该是最推荐的用法)
static void Main(string[] args)
{
   DbConnection connection = new SqlConnection("server=X;Database=XXX;uid=X;pwd=X");

   PPDbContext context = new PPDbContext(connection);

   //使用transcationscope,设置隔离等级和传播属性
   using (var transcation = new TransactionScope(TransactionScopeOption.Required,
                                               new TransactionOptions() {IsolationLevel = IsolationLevel.RepeatableRead }))
   {                       
       Person personOne = new Person();
       personOne.Name = 33;

       context.persons.Add(personOne);

       Pet petOne = new Pet();
       petOne.name = "mao1";
       petOne.owner = personOne;

       context.pets.Add(petOne);

       try
       {
           context.SaveChanges();
       }
       catch(Exception e)
       {
            //结束事务
           transcation.Dispose();
       }
       

       SOMDbcontext scontext = new SOMDbcontext(context.Database.GetDbConnection());
       //完成事务
       transcation.Complete();

       
   }

具体的TranscationScope的使用方法可以参考
https://blog.csdn.net/qq_35633131/article/details/82692854

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644666.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号