本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

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

本文章主要说了几点内容

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

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

    二 单个上下文实现事务

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

      using (var context = new BloggingContext())
                using (var transaction = context.Database.BeginTransaction())
                        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())
                        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,如需转载请自行联系原博主。

    UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库
    原文:UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库 在应用中使用 SQLite 数据库来存储数据是相当常见的。在 UWP 平台中要使用 SQLite,一般会使用 SQLite for Universal Windows Platform 和 SQLite PCL 之类的库,前者是 SQLite 引擎库,而后者则提供了用于操作数据库的 API ,不过自从 Windows Fall Creators Update 之后,我们有了新的选择。