回到目录

TransactionScope是.net平台基于的分布式事务组件,它默认为本地事务,同时当系统有需要时可以自动提升为分布式事务,而对系统的前提是要开启MSDTC服务,必要时需要在数据库服务器与应用服务器之间添加hosts的映射,这些在之前已经写过很多文章了,在这里不再说了。

之前对TransactionScope的一些理解和总结

第二十六回   将不确定变为确定~transactionscope何时提升为分布式事务?

第二十七回   将不确定变为确定~transactionscope何时提升为分布式事务~续

第二十八回   将不确定变为确定~transactionscope何时提升为分布式事务~再续(避免引起不必要的MSDTC)

第三十七回   将不确定变为确定~transactionscope何时提升为分布式事务~SQL2005与SQL2008不同

第三十八回   将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)

在efcore平台时,你使用TransactionScope将会出现异常,微软会提示你去查看相关资料,这回资料挺准!https://docs.microsoft.com/en-us/ef/core/saving/transactions

本文章主要说了几点内容

  1. 默认的事务-savechanges依旧是一个事务
  2. 单个上下文实现事务
  3. 不同上下文之间实现事务

一 savechanges依旧是一个事务

和之前的ef一样,在进行saveChanges()操作时,本身就是一个事务块,而大叔仓储习惯把每个操作curd都有自己的saveChanges里,而把数据上下文的savechanges对外隐藏,所以如果你要对两个仓储进行insert操作时,你需要添加一个外层的事务来保证数据一致性,这时微软给出了解决方案。

二 单个上下文实现事务

对于一个数据上下文来说,如果你是多个savechanges,那么可以使用context.Database.BeginTransaction()来实现事务。

  using (var context = new BloggingContext())
{
using (var transaction = context.Database.BeginTransaction())
{
try
{
context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context.SaveChanges(); context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
context.SaveChanges(); var blogs = context.Blogs
.OrderBy(b => b.Url)
.ToList(); // Commit transaction if all commands succeed, transaction will auto-rollback
// when disposed if either commands fails
transaction.Commit();
}
catch (Exception)
{
// TODO: Handle failure
}
}
}

三 不同上下文之间实现事务

对于前面的TransactionScope来说,如果是不同的数据上下文来说,我们是无法实现事务操作的,有些同学可以能说它应该被提升为分布式的,但对于EF来说,它是不同实现的,但进行efcore时代之后,这个问题得到了解决!

Cross-context transaction (relational databases only)

You can also share a transaction across multiple context instances. This functionality is only available when 
using a relational database provider because it requires the use of DbTransaction and DbConnection,
which are specific to relational databases.

上面说明,可以实现一个跨数据上下文的事务,只关系型数据库支持!这个功能大叔认为非常必要,但看它下面给出的实例是针对一个数据上下文的,并不多个上下文的交

叉事务,即并不是两个数据库之间的事务。

       using (var context1 = new BloggingContext(options))
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context1.SaveChanges(); using (var context2 = new BloggingContext(options))
{
context2.Database.UseTransaction(transaction.GetDbTransaction()); var blogs = context2.Blogs
.OrderBy(b => b.Url)
.ToList();
} // Commit transaction if all commands succeed, transaction will auto-rollback
// when disposed if either commands fails
transaction.Commit();
}
catch (Exception)
{
// TODO: Handle failure
}
}
}

而如果真正使用多个上下文进行事务的话,同样会出现问题:

           var options = new DbContextOptionsBuilder<DemoContext>()
.UseMySql("Server=localhost;DataBase=test2;UID=root;Password=root;charset=utf8;port=3306;SslMode=None")
.Options;
using (var context = new DemoContext(options))
{
using (var transaction = context.Database.BeginTransaction())
{
var user = new UserInfo
{
AddTime = DateTime.Now,
Email = "test@sina.com",
UserName = "test"
};
context.UserInfo.Add(user);
context.SaveChanges();
using (var context2 = new TaxContext())
{
context2.Database.UseTransaction(transaction.GetDbTransaction());
context2.UserInfo.Add(new UserInfo { AddTime = DateTime.Now, Email = "tax_test", UserName = "tax" });
context2.SaveChanges();
}
transaction.Commit();
}
}

出现下面异常:告诉你,你的数据库连接不是当前的连接

System.InvalidOperationException:“The specified transaction is not associated with the current connection.
Only transactions associated with the current connection may be used.”

不知道什么时候EF可以解决多数据库事务的问题,当前你可以使用最终一致性的分布式事务来做这事,不过我们还是一起期待中微软为我们提出更简单的解决方案,一个事务

是否为分布式的,应该看数据库所在服务器是否相同,而不是数据库连接串是否一致!

感谢微软这么完整的解释!

回到目录

DotNetCore跨平台~EFCore废弃了TransactionScope取而代之的Context.Database.BeginTransaction的更多相关文章

  1. DotNetCore跨平台~EFCore连接Mysql的方式

    回到目录 在.net frameworks的ef里连接mysql我们已经测试通过了,而在dotnet core里的efCore上去连接mysql我们需要测试一下,并且在测试过程中出现了一些问题,当然最 ...

  2. DotNetCore跨平台~EFCore数据上下文的创建方式

    回到目录 对于DotNetCore来说,把大部分组件者放在DI容器里,在startup中进行注入,在类的构造方法中进行使用,如果某些情况下,无法使用这种DI的方式,也可以自己控制数据上下文的生产过程, ...

  3. DotNetCore跨平台~文章索引~永久更新

    本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...

  4. DotNetCore跨平台~Quartz定时单次任务

    之前写过一篇文件<DotNetCore跨平台~Quartz热部署的福音-监控文件夹的变化>,今天主要把框架优化了一下,支持外部触发,并支持外部将参数以JobDataMap形式进行输入,然后 ...

  5. DotNetCore跨平台~Dapper的使用

    回到目录 Dapper作为小型ORM的代表作品被我们应用到了dotnet core的项目中,下面将把自己在项目中使用dapper进行curd操作的过程写一下,后期可能会遇到一些问题,大叔也会在这个系列 ...

  6. DotNetCore跨平台~聊聊中间件

    回到目录 在进行.net core平台之后,我们如果希望在请求过程中添加一些事件是非常容易的,你可以把这些事件做成一个中间件Middleware,然后这些中间件就会以Http pipeline的管道方 ...

  7. [转帖]DotNetCore跨平台~System.DrawingCore部署Linux需要注意的

    DotNetCore跨平台~System.DrawingCore部署Linux需要注意的   https://www.bbsmax.com/A/QV5ZemYVJy/?tdsourcetag=s_pc ...

  8. DotNetCore跨平台~Startup类的介绍

    新宠儿 DotNetCore是.net5.0版本,之所以不叫.net5.0为的就是不让我们把它与前面的.net混为一淡,它将是真正意义的跨平台开发语言,在网上也有相关介绍,中国的一些大牛也发了相关文章 ...

  9. DotNetCore跨平台~xUnit和测试报告

    在进入dotnet core时代之后,测试驱动开发TDD的主要工具不再是微软的nunit,取而代之的是更通用的xunit,微软把它集成到了dotnetcore的项目里,在安装完成vs2017之后,你可 ...

随机推荐

  1. Prometheus运⾏框架介绍

    框架结构的展⽰图 • 我们先来看下这个部分 这⾥是 prometheus的服务端也就是核⼼ prometheus本⾝是⼀个以进程⽅式启动,之后以多进程和多线程实现监控数据收集 计算 查询 更新 存储 ...

  2. multiWriter.go

    package blog4go import ( "errors" "fmt" ) var ( // ErrFilePathNotFound 文件路径找不到 E ...

  3. 理解Go Context机制

    1 什么是Context 最近在公司分析gRPC源码,proto文件生成的代码,接口函数第一个参数统一是ctx context.Context接口,公司不少同事都不了解这样设计的出发点是什么,其实我也 ...

  4. 【Floyd】BZOJ1491: [NOI2007]社交网络

    Description   Solution n<=100自然联想Floyd 设两个数组d[n][n]存最短距离,t[n][n]存最短路径条数 更新d的时候顺便更新t,乘法原理 if(d[i][ ...

  5. BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元

    BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...

  6. BZOJ_3427_Poi2013 Bytecomputer_DP

    BZOJ_3427_Poi2013 Bytecomputer_DP Description 给定一个{-1,0,1}组成的序列,你可以进行x[i]=x[i]+x[i-1]这样的操作,求最少操作次数使其 ...

  7. mysql中利用group by过滤删除重复行

    DELETEFROM peopleWHERE peopleId IN (SELECT peopleId FROM people GROUP BY peopleId HAVING count(peopl ...

  8. 迎元旦,庆surging 1.0发布

    一位摄影程序员的独白 每个人都有爱好,都有释放压力的活动,而我也不例外,我除了每天上班,周末就会约一群好友去拍妹子,成家后,就改为拍虫子,一拍就到了30岁,到了30岁就感觉到了中年的压力,这时候停下手 ...

  9. c# 基于文件系统实现的队列处理类

    现实业务中经常遇到需要队列处理的问题. 问题场景: 客户端记录设备运行数据,传输给服务器.在传输中可能存在延迟或中断情况.当中断时,系统传输数据可能因为无法传输或电脑重启,会导致服务器数据记录不连续. ...

  10. Java语言编程 - 搭建Java开发环境

    2.1 JDK.JRE和JVM关系 要弄清楚JDK.JRE和JVM这三者之间的关系,先看如下图,有个感性的认识: JDK:Java Development ToolKit(Java开发工具包).JDK ...