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<Person> persons { get; set; }
   
   public DbSet<Pet> 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());
          
          /*
			数据库上下文2Todo Something
			*/
         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<BloggingContext>()
        .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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 ABP 应用程序中,您可以使用 Dapper 和 Entity Framework Core 两种 ORM 工具之一,或者甚至可以同时使用它们来访问数据库。以下是如何在 ABP 应用程序中同时使用 Dapper 和 Entity Framework Core 的步骤: 1.添加 Dapper 和 Entity Framework Core 的依赖项 在您的 ABP 应用程序中,您需要添加 Dapper 和 Entity Framework Core 的依赖项。您可以通过 NuGet 包管理器或手动编辑项目文件添加这些依赖项。添加 Dapper 和 Entity Framework Core 的依赖项后,您需要在 `Startup.cs` 文件中配置它们。 2.配置 Dapper 和 Entity Framework Core 在 `Startup.cs` 文件中,您需要配置 Dapper 和 Entity Framework Core。以下是一个示例: ```csharp public void ConfigureServices(IServiceCollection services) { // Add Dapper services.AddScoped<IDbConnection>(x => new SqlConnection(Configuration.GetConnectionString("Default"))); // Add Entity Framework Core services.AddAbpDbContext<MyProjectDbContext>(options => { options.AddDefaultRepositories(includeAllEntities: true); }); } ``` 在上面的代码中,我们使用 `AddScoped` 方法将 `IDbConnection` 注册为一个服务,并指定使用 `SqlConnection` 类创建连接。然后,我们使用 `AddAbpDbContext` 方法将 `MyProjectDbContext` 注册为一个服务,并指定包含所有实体。 3.编写 Dapper 和 Entity Framework Core 的查询 在您的应用程序中,您可以使用 Dapper 和 Entity Framework Core 的查询来访问数据库。以下是一个示例: ```csharp public class MyService : ITransientDependency { private readonly IDbConnection _connection; private readonly IRepository<MyEntity> _repository; public MyService(IDbConnection connection, IRepository<MyEntity> repository) { _connection = connection; _repository = repository; } public async Task<MyEntity> GetEntity(int id) { // Use Dapper var entity = await _connection.QueryFirstOrDefaultAsync<MyEntity>("SELECT * FROM MyEntities WHERE Id = @Id", new { Id = id }); // Use Entity Framework Core entity = await _repository.GetAsync(id); return entity; } } ``` 在上面的代码中,我们注入 `IDbConnection` 和 `IRepository<MyEntity>`,并在 `GetEntity` 方法中使用它们来执行 Dapper 和 Entity Framework Core 的查询。 需要注意的是,使用 Dapper 和 Entity Framework Core 的查询时,您需要务必遵循正确的事务处理和连接管理方式,以确保应用程序的数据完整性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗马苏丹默罕默德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值