前言:
数据库事务想必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参与事务)
前提:
- 必须是关系型数据库
- 必须共享同一个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