数据库


我们先在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'')
GO
INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'English', N'English', N'')
GO
INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Japanese', N'Japanese', N'')
GO
INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Russian', N'Russian', N'')
GO
INSERT [dbo].[Book] ([BookName], [BookDescription], [ISBN]) VALUES (N'Italian', N'Italian', N'')
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方法开启的数据库连接,所以这和没有使用事务的时候是完全不一样的。

EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响的更多相关文章

  1. EF Core 1.0中使用Include的小技巧

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:由于EF Core暂时不支持Lazy Loading,所以利用Include来加载额外 ...

  2. EF Core 2.0中如何手动映射数据库的视图为实体

    由于Scaffold-DbContext指令目前还不支持自动映射数据库中的视图为实体,所以当我们想使用EF Core来读取数据库视图数据的时候,我们需要手动去做映射,本文介绍如何在EF Core中手动 ...

  3. EF Core 2.0中怎么用DB First通过数据库来生成实体

    要在EF Core使用DB First首先要下载三个Nuget包,在Nuget的Package Manager Console窗口中依次敲入下面三个命令即可: Microsoft.EntityFram ...

  4. EF Core 2.0 新特性

    前言 目前 EF Core 的最新版本为 2.0.0-priview1-final,所以本篇文章主要是针对此版本的一些说明. 注意:如果你要在Visual Studio 中使用 .NET Core 2 ...

  5. 【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  6. EF Core 2.0 执行原始查询如何防止SQL注入

    using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky Wang"; Formattab ...

  7. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  8. EF Core 6.0的新计划

    今天,我们很兴奋地与你分享Entity Framework Core 6.0的计划. 这个计划汇集了许多人的意见,并概述了我们打算在哪里以及如何优化实体框架(EF Core) 6.0版本.这个计划并不 ...

  9. EF Core 2.0 已经支持自动生成父子关系表的实体

    现在我们在SQL Server数据库中有Person表如下: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

随机推荐

  1. golang 使用rrd的相关资料

    一.简介      RRDtool是指Round Robin Database工具,即环状数据库.从功能上说,RRDtool可用于数据存储+数据展示.著名的网络流量绘图软件MRTG和集群监控系统Gan ...

  2. 纪念一个神坑——react-native-echarts

    一.问题 在rn项目里引用的时候,本该显示图表的界面显示出了一堆html... 二.原因 官方没给配置好 三.解决 1./node_modules/native-echarts/src/compone ...

  3. flask 简易注册登陆

    db.py import MySQLdb conn = MySQLdb.connect(', 'test1') cur = conn.cursor() def addUser (username,pa ...

  4. jQuery——子元素筛选器

    子元素筛选器 名称 :first-child JQ语法 jQuery( "selector:first-child" ) 说明 :first-child选择器用于匹配作为父元素的第 ...

  5. Mybatis学习随笔

    学习Mybatis路径(适合有java基础和mysql基础的小伙伴) 1.把项目搭建起来,跑一跑感受一下 2.测试基本映射 3.测试高级映射 4.测试动态sql 5.学习懒加载与缓存 6.与sprin ...

  6. iview中关于table组件内放入Input会失去焦点

    table里面的数据是一个数组,父组件传入的.子组件是截图的内容.当每个input框数据发生变化时,把数据传给父组件.在父组件做表单的提交. github内已经提到过这个问题(https://gith ...

  7. Java基础_day01

    一.JRE和JDK的安装,     JRE ——    Java   运行环境      Java runtime environment      包含Java虚拟机和Java程序的核心类库.   ...

  8. eclipse svn使用

    简单介绍一些基本操作 1.同步在Eclipse下,右击你要同步的工程->team->与资源库同步->这时会进入同步透视图,会显示出本机与SVN上内容有不同的文件,双击文件名,会显示出 ...

  9. Android 6.0+ 运行时权限

    1.权限被分为了普通和危险两种 2.打电话的Demo import android.Manifest; import android.app.Activity; import android.cont ...

  10. Ubuntu 中QT 用sogou拼音 安装

    1.下载搜狗输入法的安装包 下载地址为:http://pinyin.sogou.com/linux/ ,如下图,要选择与自己系统位数一致的安装包,我的系统是64位,所以我下载64位的安装包 2.按键C ...