zoukankan      html  css  js  c++  java
  • EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响

    数据库


    我们先在SQL Server数据库中建立一个Book表:

    CREATE TABLE [dbo].[Book](
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [BookName] [nvarchar](50) NULL,
        [BookDescription] [nvarchar](50) NULL,
        [ISBN] [nvarchar](20) NULL,
        [CreateTime] [datetime] NULL,
     CONSTRAINT [PK_Book] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    
    ALTER TABLE [dbo].[Book] ADD  CONSTRAINT [DF_Book_CreateTime]  DEFAULT (getdate()) FOR [CreateTime]
    GO

    然后插入如下数据:

    INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Chinese', N'Chinese', N'0001')
    GO
    INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'English', N'English', N'0002')
    GO
    INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Japanese', N'Japanese', N'0003')
    GO
    INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Russian', N'Russian', N'0004')
    GO
    INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Italian', N'Italian', N'0005')
    GO

    查询Book表的数据,如下图所示:

    现在我们使用EF Core将Book表映射到.NET Core控制台项目中的Book实体上,Book实体如下所示:

    using System;
    using System.Collections.Generic;
    
    namespace EFCoreDB.Entities
    {
        public partial class Book
        {
            public int Id { get; set; }
            public string BookName { get; set; }
            public string BookDescription { get; set; }
            public string Isbn { get; set; }
            public DateTime? CreateTime { get; set; }
        }
    }

    不使用事务


    然后我们在.NET Core控制台项目Program类的Main方法中,使用DbContext(也就是FinanceDigitalToolContext)读取BookName为"Chinese"的Book实体,然后使用DbContext.SaveChanges方法两次更改其BookDescription属性的值,再从数据库中将其查询出来显示,代码如下:

    using EFCoreDB.Entities;
    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace EFCoreDB
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
                {
                    Expression<Func<Book, bool>> bookExpression = b => b.BookName == "Chinese";//构造查询条件,来查询BookName为Chinese的Book
    
                    var chineseBook = dbContext.Book.First(bookExpression);//获取BookName为Chinese的Book实体chineseBook
    
                    chineseBook.BookDescription = "This is a Chinese book";//更改chineseBook的BookDescription属性
                    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库
    
                    chineseBook.BookDescription = "This is a very good Chinese book";//再次更改chineseBook的BookDescription属性
                    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库
    
                    chineseBook = dbContext.Book.First(bookExpression);//重新获取BookName为Chinese的Book实体chineseBook
    
                    //显示当前chineseBook的当前BookDescription属性值
                    Console.WriteLine(chineseBook.BookName + " book has description: "" + chineseBook.BookDescription + """);
                }
    
                Console.WriteLine("Press key to quit....");
    
                Console.ReadLine();
            }
        }
    }

    执行上面的代码,我们使用EF Core的日志功能,输出每次DbContext访问数据库时的后台日志信息:

    首先在执行

    var chineseBook = dbContext.Book.First(bookExpression);//获取BookName为Chinese的Book实体chineseBook

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (129ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Context 'Book' started tracking 'FinanceDigitalToolContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来,dbContext.Book.First(bookExpression)在数据库中开启了一个数据库连接,并使用SQL语句做了查询,然后关闭了数据库连接。

    然后在执行下面的代码

    chineseBook.BookDescription = "This is a Chinese book";//更改chineseBook的BookDescription属性
    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    SaveChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Unchanged 'Book.BookDescription' detected as changed and will be marked as modified. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see property values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Unchanged' to 'Modified'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges completed for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Beginning transaction with isolation level 'ReadCommitted'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (86ms) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Committing transaction.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Disposing transaction.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Modified' to 'Unchanged'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    SaveChanges completed for 'FinanceDigitalToolContext' with 1 entities written to the database.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来在执行dbContext.SaveChanges方法时,EF Core在数据库中开启了一个数据库连接,并使用SQL语句做了数据库更改,然后关闭了数据库连接。然后chineseBook这个Book实体的EntityState从Modified变为了Unchanged。

    然后执行代码

    chineseBook.BookDescription = "This is a very good Chinese book";//再次更改chineseBook的BookDescription属性
    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    SaveChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Unchanged 'Book.BookDescription' detected as changed and will be marked as modified. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see property values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Unchanged' to 'Modified'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges completed for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Beginning transaction with isolation level 'ReadCommitted'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (19ms) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Committing transaction.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Disposing transaction.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Modified' to 'Unchanged'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    SaveChanges completed for 'FinanceDigitalToolContext' with 1 entities written to the database.
    =============================== EF Core log finished ===============================

    同样从日志中我们可以看出来在执行dbContext.SaveChanges方法时,EF Core在数据库中开启了一个数据库连接,并使用SQL语句做了数据库更改,然后关闭了数据库连接。然后chineseBook这个Book实体的EntityState从Modified变为了Unchanged。

    然后执行代码

    chineseBook = dbContext.Book.First(bookExpression);//重新获取BookName为Chinese的Book实体chineseBook

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (21ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来,dbContext.Book.First(bookExpression)在数据库中还是开启了一个数据库连接,并使用SQL语句做了查询,然后关闭了数据库连接。

    总结下来,上面的代码和日志发生的事情如下:

    • dbContext.Book.First(bookExpression)开启和关闭了一个数据库连接,查询BookName为Chinese的Book实体chineseBook
    • 第一个dbContext.SaveChanges()开启和关闭了一个数据库连接,更改chineseBook的BookDescription属性值"This is a Chinese book"到数据库
    • 第二个dbContext.SaveChanges()开启和关闭了一个数据库连接,更改chineseBook的BookDescription属性值"This is a very good Chinese book"到数据库
    • dbContext.Book.First(bookExpression)开启和关闭了一个数据库连接,重新查询BookName为Chinese的Book实体chineseBook

    所以综上所述DbContext一共开启了和关闭了四个数据库连接。

    使用事务


    现在我们更改Program类Main方法中的代码,将两次DbContext.SaveChanges方法的调用都放在一个TransactionScope事务范围中,所以现在两次DbContext.SaveChanges方法提交的SQL都会在同一个数据库事务中,代码如下所示:

    using EFCoreDB.Entities;
    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Transactions;
    
    namespace EFCoreDB
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
                {
                    Expression<Func<Book, bool>> bookExpression = b => b.BookName == "Chinese";//构造查询条件,来查询BookName为Chinese的Book
    
                    var chineseBook = dbContext.Book.First(bookExpression);//获取BookName为Chinese的Book实体chineseBook
    
                    //使用TransactionScope事务范围来开启一个数据库事务
                    using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
                    {
                        chineseBook.BookDescription = "This is a Chinese book";//更改chineseBook的BookDescription属性
                        dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库,由于TransactionScope事务范围的存在,所以DbContext.SaveChanges方法提交的SQL语句都存在于TransactionScope的事务当中
    
                        chineseBook.BookDescription = "This is a very good Chinese book";//再次更改chineseBook的BookDescription属性
                        dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库,由于TransactionScope事务范围的存在,所以DbContext.SaveChanges方法提交的SQL语句都存在于TransactionScope的事务当中
    
                        transactionScope.Complete();//提交TransactionScope事务范围中的SQL语句到数据库,数据库事务结束
                    }
    
                    chineseBook = dbContext.Book.First(bookExpression);//重新获取BookName为Chinese的Book实体chineseBook
    
                    //显示当前chineseBook的当前BookDescription属性值
                    Console.WriteLine(chineseBook.BookName + " book has description: "" + chineseBook.BookDescription + """);
                }
    
                Console.WriteLine("Press key to quit....");
    
                Console.ReadLine();
            }
        }
    }

    执行上面的代码,我们还是使用EF Core的日志功能,输出每次DbContext访问数据库时的后台日志信息:

    首先执行

    var chineseBook = dbContext.Book.First(bookExpression);//获取BookName为Chinese的Book实体chineseBook

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (139ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Context 'Book' started tracking 'FinanceDigitalToolContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来,dbContext.Book.First(bookExpression)在数据库中开启了一个数据库连接,并使用SQL语句做了查询,然后关闭了数据库连接。

    然后执行

    using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
    {

    TransactionScope的事务范围开始,此时数据库事务已经开始,EF Core没有输出日志

    然后执行

    chineseBook.BookDescription = "This is a Chinese book";//更改chineseBook的BookDescription属性
    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库,由于TransactionScope事务范围的存在,所以DbContext.SaveChanges方法提交的SQL语句都存在于TransactionScope的事务当中

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    SaveChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Unchanged 'Book.BookDescription' detected as changed and will be marked as modified. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see property values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Unchanged' to 'Modified'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges completed for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opening connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Opened connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Enlisted in an ambient transaction with isolation level 'Serializable'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (79ms) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Modified' to 'Unchanged'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    SaveChanges completed for 'FinanceDigitalToolContext' with 1 entities written to the database.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来在执行dbContext.SaveChanges方法时,EF Core在数据库中开启了一个数据库连接,并使用SQL语句做了数据库更改,但是没有关闭数据库连接。然后chineseBook这个Book实体的EntityState从Modified变为了Unchanged。

    然后执行

    chineseBook.BookDescription = "This is a very good Chinese book";//再次更改chineseBook的BookDescription属性
    dbContext.SaveChanges();//用DbContext.SaveChanges方法保存更改到数据库,由于TransactionScope事务范围的存在,所以DbContext.SaveChanges方法提交的SQL语句都存在于TransactionScope的事务当中

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    SaveChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges starting for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Unchanged 'Book.BookDescription' detected as changed and will be marked as modified. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see property values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Unchanged' to 'Modified'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    DetectChanges completed for 'FinanceDigitalToolContext'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (22ms) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
    SET NOCOUNT ON;
    UPDATE [Book] SET [BookDescription] = @p0
    WHERE [ID] = @p1;
    SELECT @@ROWCOUNT;
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    An 'Book' entity tracked by 'FinanceDigitalToolContext' changed from 'Modified' to 'Unchanged'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    SaveChanges completed for 'FinanceDigitalToolContext' with 1 entities written to the database.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来在执行dbContext.SaveChanges方法时,EF Core在数据库中并没有开启新的数据库连接,而是沿用了上一个DbContext.SaveChanges方法开启的数据库连接来提交SQL语句到数据库。然后chineseBook这个Book实体的EntityState从Modified变为了Unchanged。

    然后执行

        transactionScope.Complete();//提交TransactionScope事务范围中的SQL语句到数据库,数据库事务结束
    }

    提交TransactionScope的事务到数据库,此时数据库事务结束,TransactionScope的事务范围也结束,EF Core没有输出日志

    然后执行

    chineseBook = dbContext.Book.First(bookExpression);//重新获取BookName为Chinese的Book实体chineseBook

    时,EF Core的日志如下所示:

    =============================== EF Core log started ===============================
    Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Executed DbCommand (24ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    SELECT TOP(1) [b].[ID], [b].[BookDescription], [b].[BookName], [b].[CreateTime], [b].[ISBN]
    FROM [Book] AS [b]
    WHERE [b].[BookName] = N'Chinese'
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    A data reader was disposed.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closing connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================
    =============================== EF Core log started ===============================
    Closed connection to database 'FinanceDigitalTool' on server 'CNGDCAAITSQL01'.
    =============================== EF Core log finished ===============================

    从日志中我们可以看出来,dbContext.Book.First(bookExpression)在数据库中也没有开启新的数据库连接,而是继续沿用了第一个DbContext.SaveChanges方法开启的数据库连接,使用SQL语句做了查询,之后关闭了第一个DbContext.SaveChanges方法开启的数据库连接,所以可以看到第一个DbContext.SaveChanges方法开启的数据库连接,现在才被关闭,这和不使用事务时是完全不一样的。

    总结下来,使用事务后的代码和日志发生的事情如下:

    • dbContext.Book.First(bookExpression)开启和关闭了一个数据库连接,查询BookName为Chinese的Book实体chineseBook
    • using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew)){开启了TransactionScope事务范围,数据库事务开始
    • 第一个dbContext.SaveChanges()开启一个数据库连接,但是没有关闭数据库连接,更改chineseBook的BookDescription属性值"This is a Chinese book"到数据库
    • 第二个dbContext.SaveChanges()没有开启新的数据库连接,而是沿用了上一个DbContext.SaveChanges方法开启的数据库连接,更改chineseBook的BookDescription属性值"This is a very good Chinese book"到数据库
    • transactionScope.Complete()提交TransactionScope事务范围的数据库事务到数据库,数据库事务结束
    • }TransactionScope事务范围结束
    • dbContext.Book.First(bookExpression)没有开启新的数据库连接,而是沿用了第一个DbContext.SaveChanges方法开启的数据库连接,重新查询BookName为Chinese的Book实体chineseBook,最后关闭了第一个DbContext.SaveChanges方法开启的数据库连接。

    所以综上所述DbContext这次一共只开启和关闭了两个数据库连接,并且第二个数据库连接执行了三次数据库操作(两次DbContext.SaveChanges更改数据,一次Book.First查询数据)才被关闭。

    由此我们可以看到EF Core在处于事务中时,会优化底层开启和关闭数据库连接的机制,因为EF Core觉得两次DbContext.SaveChanges方法提交的SQL语句既然都在同一个事务中,所以就没有必要每次都开启和关闭一个数据库连接,而是沿用了第一次DbContext.SaveChanges方法开启的数据库连接,所以这和没有使用事务的时候是完全不一样的。

  • 相关阅读:
    wireshark安装
    高效使用搜索引擎
    MFC 网络编程 -- 总结
    MFC Grid control 2.27
    A Popup Progress Window
    Showing progress bar in a status bar pane
    Progress Control with Text
    Report List Controls
    第三方
    CBarChart柱形图类
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/9803032.html
Copyright © 2011-2022 走看看