第三節:EF Core上下文DbContext相關配置和生命周期


一. 配置相關

1. 數據庫連接字符串的寫法

(1).賬號密碼:Server=localhost;Database=EFDB01;User ID=sa;Password=123456;

(2).windows身份:Server=localhost;Database=EFDB01;Trusted_Connection=True;

2. 命令超時和默認關閉狀態追蹤

(1).命令超時: providerOptions => providerOptions.CommandTimeout(60),表示60秒超時。

(2).關閉查詢狀態追蹤:UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking),表示關閉追蹤;

(PS: 默認是 QueryTrackingBehavior.TrackAll 開啟追蹤)

 詳見下面案例:

  a. QueryTrackingBehavior.NoTracking: 對應的是Detached狀態,即有游離狀態。

  b. QueryTrackingBehavior.TrackAll: 對應的是Unchanged狀態,即未發生改變的。

 

1             {
2                 var d1 = context1.T_UserInfor.First();
3                 //關閉跟蹤對應的是:Detached;開啟跟蹤對應的是:Unchanged
4                 var state = context1.Entry(d1).State;
5             }

3. 日志記錄

  最好在控制台中配置,能輸出生成的SQL語句。 

配置代碼分享:

 1  public partial class EFDB01Context : DbContext
 2     {
 3         //public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });
 4         public static readonly LoggerFactory MyLoggerFactory  = new LoggerFactory(new[]
 5          {
 6                 new ConsoleLoggerProvider((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information, true)
 7          });
 8         public EFDB01Context()
 9         {
10 
11         }
12         public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
13         public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
14         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
15         {
16             optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;").UseLoggerFactory(MyLoggerFactory);
17         } 
18     }

輸出結果:

4. 連接彈性

    詳見官方文章:https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/connection-resiliency

5. 線程安全問題

(1).說明

  EF Core不支持在同一DbContext實例上運行多個並行操作。這包括異步查詢的並行執行以及從多個線程進行的任何顯式並發使用。因此,應await立即異步調用, 或對並行DbContext執行的操作使用單獨的實例。

  當EFCore檢測到並行使用某個DbContext實例時, 觸發InvalidOperationException異常;但是當並發訪問未被檢測時, 可能會導致未定義的行為、應用程序崩潰和數據損壞.

(2).情況一:在對同一 DbContext 啟動任何其他操作之前, 忘記等待異步操作完成。

  使用異步方法, EF Core 可以啟動以非阻止方式訪問數據庫的操作。 但是, 如果調用方不等待其中一種方法完成, 並繼續在上DbContext執行其他操作,則的DbContext狀態可能會損壞。

(3).情況二:Core MVC通過依賴關系注入在多個線程之間隱式共享 DbContext 實例

   默認AddDbContext情況下,注入的上下文是請求內單例的,所以每個請求都獲得了單獨的DbContext,請求與請求之間的DbContext是線程安全的;但是,在同一個請求中,任何並行顯式執行多個線程的代碼都應該DbContext確保不會同時訪問實例,否則會出現上述“情況一”的狀況。

(4). 案例說明:要避免下面案例的那種情況,公用同一個上下文,是沒法保證線程安全的

代碼分享:

 1             {
 2                 var optionsBuilder = new DbContextOptionsBuilder<EFDB01Context>();
 3                 optionsBuilder.UseSqlServer(configuration.GetConnectionString("EFStr"));
 4                 EFDB01Context context = new EFDB01Context(optionsBuilder.Options);
 5                 Task.Run(() =>
 6                 {
 7                     while (true)
 8                     {
 9                         var u1 = new T_UserInfor()
10                         {
11                             id = Guid.NewGuid().ToString("N"),
12                             userName = "ypf2",
13                             userSex = "男2",
14                             userAge = 19,
15                             addTime = DateTime.Now
16                         };
17                         context.Set<T_UserInfor>().Add(u1);
18                         int result = context.SaveChanges();
19                     }
20                 });
21 
22                 Task.Run(() =>
23                 {
24                     while (true)
25                     {
26                         var u1 = new T_UserInfor()
27                         {
28                             id = Guid.NewGuid().ToString("N"),
29                             userName = "ypf2",
30                             userSex = "男2",
31                             userAge = 19,
32                             addTime = DateTime.Now
33                         };
34                         context.Set<T_UserInfor>().Add(u1);
35                         int result = context.SaveChanges();
36                     }
37                 });
38                 Task.Delay(TimeSpan.FromMinutes(15)).Wait();
39             }

6. 連接數和連接池問題

(1).查詢數據庫連接數語句:SELECT * FROM SYSPROCESSES WHERE DBID = DB_ID('數據庫名')

(2).手動設置連接池的最大(小)數量 "Server=localhost;Database=Test;Trusted_Connection=True;Max Pool Size=100;Min Pool Size=5"

(3).連接池的運行原理

概念連接到數據源可能需要很長時間。 為了最大程度地降低打開連接的成本,ADO.NET 使用一種稱為連接池的優化技術,這會最大程度地降低重復打開和關閉連接的成本。

A. 當一個程序執行Connection.open()時候,ADO.Net就需要判斷,此連接是否支持Connection Pool (Pooling 默認為True)

 ①:如果指定為False, ADO.Net就與數據庫之間創建一個連接,然后返回給程序。

 ②:如果指定為 True,ADO.Net就會根據ConnectString創建一個Connection Pool,然后向Connection Pool中填充Connection。填充多少個Connection由Min Pool Size (默認為0)屬性來決定。例如如果指定為5,則ADO.Net會一次與SQL數據庫之間打開5個連接,然后將4個Connection,保存在 Connection Pool中,1個Connection返回給程序。

B. 當程序執行到Connection.close() 的時候。如果Pooling 為True,ADO.net 就把當前的Connection放到Connection Pool並且保持與數據庫之間的連接。

同時還會判斷Connection Lifetime(默認為0)屬性,0代表無限大,如果Connection存在的時間超過了Connection LifeTime,ADO.net就會關閉的Connection同時斷開與數據庫的連接,而不是重新保存到Connection Pool中。

C. 當下一次Connection.Open() 執行的時候,ADO.Net就會判斷新的ConnectionString與之前保存在Connection Pool中的Connection的connectionString是否一致。

D. ADO.Net需要判斷當前的Connection Pool中是否有可以使用的Connection(沒有被其他程序所占用),如果沒有的話,ADO.Net就需要判斷ConnectionString設 置的Max Pool Size (默認為100)

 ①. 如果Connection Pool中的所有Connection沒有達到Max Pool Size,ADO.net則會再次連接數據庫,創建一個連接,然后將Connection返回給程序。

 ②. 如果已經達到了 Max Pool Size,ADO.Net就不會再次創建任何新的連接,而是等待Connection Pool中被其他程序所占用的Connection釋放,這個等待時間受SqlConnection.ConnectionTimeout(默認是15 秒)限制,也就是說如果時間超過了15秒,SqlConnection就會拋出超時錯誤。

E. 如果有可用的Connection,從Connection Pool 取出的Connection也不是直接就返回給程序,ADO.Net還需要檢查ConnectionString的ConnectionReset屬性 (默認為True)是否需要對Connection 做一次reset。

更詳細的介紹請參考官方文檔:https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql-server-connection-pooling

7. 總結

(1).SaveChanges的時候數據庫連接自動釋放,所以不需要手動釋放。

(2).調用using的方法可以,因為dispose里講很多東西都滯空了,完全沒問題;但在Core MVC中,EF上下文都是通過依賴注入,能控制生命周期,所以不再需要using。

(3).手動open然后手動close,連接數沒有釋放,因為連接池的概念,當然你可以手動配置連接池數目(強制刪除連接池:ClearAllPools),只有當IIS關閉,連接才徹底釋放。

 

二. 生命周期

1.源碼分析 

public enum ServiceLifetime { Singleton = 0, Scoped = 1, Transient = 2 }

(1).Singleton :整個應用程序生命周期以內只創建一個實例。

(2).Scoped: 在同一個Scope內只初始化一個實例 ,可以理解為(每一個 request 級別只創建一個實例)

(3).Transient: 每一次 GetService 都會創建一個新的實例。

注:默認是Scoped,即單次請求內是單例的。

 可以自行配置:

 

 通過查源碼可知,默認就是Scoped的。

 

  1  //
  2     // 摘要:
  3     //     Extension methods for setting up Entity Framework related services in an Microsoft.Extensions.DependencyInjection.IServiceCollection.
  4     public static class EntityFrameworkServiceCollectionExtensions
  5     {
  6         //
  7         // 摘要:
  8         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
  9         //     You use this method when using dependency injection in your application, such
 10         //     as with ASP.NET. For more information on setting up dependency injection, see
 11         //     http://go.microsoft.com/fwlink/?LinkId=526890.
 12         //
 13         // 參數:
 14         //   serviceCollection:
 15         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
 16         //     to.
 17         //
 18         //   optionsAction:
 19         //     An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
 20         //     for the context. This provides an alternative to performing configuration of
 21         //     the context by overriding the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 22         //     method in your derived context.
 23         //     If an action is supplied here, the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 24         //     method will still be run if it has been overridden on the derived context. Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 25         //     configuration will be applied in addition to configuration performed here.
 26         //     In order for the options to be passed into your context, you need to expose a
 27         //     constructor on your context that takes Microsoft.EntityFrameworkCore.DbContextOptions`1
 28         //     and passes it to the base constructor of Microsoft.EntityFrameworkCore.DbContext.
 29         //
 30         //   contextLifetime:
 31         //     The lifetime with which to register the DbContext service in the container.
 32         //
 33         //   optionsLifetime:
 34         //     The lifetime with which to register the DbContextOptions service in the container.
 35         //
 36         // 類型參數:
 37         //   TContext:
 38         //     The type of context to be registered.
 39         //
 40         // 返回結果:
 41         //     The same service collection so that multiple calls can be chained.
 42         public static IServiceCollection AddDbContext<TContext>([NotNullAttribute] this IServiceCollection serviceCollection, [CanBeNullAttribute] Action<DbContextOptionsBuilder> optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext;
 43         //
 44         // 摘要:
 45         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
 46         //     You use this method when using dependency injection in your application, such
 47         //     as with ASP.NET. For more information on setting up dependency injection, see
 48         //     http://go.microsoft.com/fwlink/?LinkId=526890.
 49         //
 50         // 參數:
 51         //   serviceCollection:
 52         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
 53         //     to.
 54         //
 55         //   optionsAction:
 56         //     An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
 57         //     for the context. This provides an alternative to performing configuration of
 58         //     the context by overriding the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 59         //     method in your derived context.
 60         //     If an action is supplied here, the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 61         //     method will still be run if it has been overridden on the derived context. Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
 62         //     configuration will be applied in addition to configuration performed here.
 63         //     In order for the options to be passed into your context, you need to expose a
 64         //     constructor on your context that takes Microsoft.EntityFrameworkCore.DbContextOptions`1
 65         //     and passes it to the base constructor of Microsoft.EntityFrameworkCore.DbContext.
 66         //
 67         //   contextLifetime:
 68         //     The lifetime with which to register the DbContext service in the container.
 69         //
 70         //   optionsLifetime:
 71         //     The lifetime with which to register the DbContextOptions service in the container.
 72         //
 73         // 類型參數:
 74         //   TContextService:
 75         //     The class or interface that will be used to resolve the context from the container.
 76         //
 77         //   TContextImplementation:
 78         //     The concrete implementation type to create.
 79         //
 80         // 返回結果:
 81         //     The same service collection so that multiple calls can be chained.
 82         public static IServiceCollection AddDbContext<TContextService, TContextImplementation>([NotNullAttribute] this IServiceCollection serviceCollection, [CanBeNullAttribute] Action<DbContextOptionsBuilder> optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService;
 83         //
 84         // 摘要:
 85         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
 86         //     You use this method when using dependency injection in your application, such
 87         //     as with ASP.NET. For more information on setting up dependency injection, see
 88         //     http://go.microsoft.com/fwlink/?LinkId=526890.
 89         //
 90         // 參數:
 91         //   serviceCollection:
 92         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
 93         //     to.
 94         //
 95         //   contextLifetime:
 96         //     The lifetime with which to register the DbContext service in the container.
 97         //
 98         //   optionsLifetime:
 99         //     The lifetime with which to register the DbContextOptions service in the container.
100         //
101         // 類型參數:
102         //   TContext:
103         //     The type of context to be registered.
104         //
105         // 返回結果:
106         //     The same service collection so that multiple calls can be chained.
107         public static IServiceCollection AddDbContext<TContext>([NotNullAttribute] this IServiceCollection serviceCollection, ServiceLifetime contextLifetime, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext;
108         //
109         // 摘要:
110         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
111         //     You use this method when using dependency injection in your application, such
112         //     as with ASP.NET. For more information on setting up dependency injection, see
113         //     http://go.microsoft.com/fwlink/?LinkId=526890.
114         //
115         // 參數:
116         //   serviceCollection:
117         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
118         //     to.
119         //
120         //   contextLifetime:
121         //     The lifetime with which to register the DbContext service in the container.
122         //
123         //   optionsLifetime:
124         //     The lifetime with which to register the DbContextOptions service in the container.
125         //
126         // 類型參數:
127         //   TContextService:
128         //     The class or interface that will be used to resolve the context from the container.
129         //
130         //   TContextImplementation:
131         //     The concrete implementation type to create.
132         //
133         // 返回結果:
134         //     The same service collection so that multiple calls can be chained.
135         public static IServiceCollection AddDbContext<TContextService, TContextImplementation>([NotNullAttribute] this IServiceCollection serviceCollection, ServiceLifetime contextLifetime, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
136             where TContextService : class
137             where TContextImplementation : DbContext, TContextService;
138         //
139         // 摘要:
140         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
141         //     You use this method when using dependency injection in your application, such
142         //     as with ASP.NET. For more information on setting up dependency injection, see
143         //     http://go.microsoft.com/fwlink/?LinkId=526890.
144         //     This overload has an optionsAction that provides the applications System.IServiceProvider.
145         //     This is useful if you want to setup Entity Framework to resolve its internal
146         //     services from the primary application service provider. By default, we recommend
147         //     using the other overload, which allows Entity Framework to create and maintain
148         //     its own System.IServiceProvider for internal Entity Framework services.
149         //
150         // 參數:
151         //   serviceCollection:
152         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
153         //     to.
154         //
155         //   optionsAction:
156         //     An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
157         //     for the context. This provides an alternative to performing configuration of
158         //     the context by overriding the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
159         //     method in your derived context.
160         //     If an action is supplied here, the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
161         //     method will still be run if it has been overridden on the derived context. Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
162         //     configuration will be applied in addition to configuration performed here.
163         //     In order for the options to be passed into your context, you need to expose a
164         //     constructor on your context that takes Microsoft.EntityFrameworkCore.DbContextOptions`1
165         //     and passes it to the base constructor of Microsoft.EntityFrameworkCore.DbContext.
166         //
167         //   contextLifetime:
168         //     The lifetime with which to register the DbContext service in the container.
169         //
170         //   optionsLifetime:
171         //     The lifetime with which to register the DbContextOptions service in the container.
172         //
173         // 類型參數:
174         //   TContext:
175         //     The type of context to be registered.
176         //
177         // 返回結果:
178         //     The same service collection so that multiple calls can be chained.
179         public static IServiceCollection AddDbContext<TContext>([NotNullAttribute] this IServiceCollection serviceCollection, [CanBeNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext;
180         //
181         // 摘要:
182         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection.
183         //     You use this method when using dependency injection in your application, such
184         //     as with ASP.NET. For more information on setting up dependency injection, see
185         //     http://go.microsoft.com/fwlink/?LinkId=526890.
186         //     This overload has an optionsAction that provides the applications System.IServiceProvider.
187         //     This is useful if you want to setup Entity Framework to resolve its internal
188         //     services from the primary application service provider. By default, we recommend
189         //     using the other overload, which allows Entity Framework to create and maintain
190         //     its own System.IServiceProvider for internal Entity Framework services.
191         //
192         // 參數:
193         //   serviceCollection:
194         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
195         //     to.
196         //
197         //   optionsAction:
198         //     An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
199         //     for the context. This provides an alternative to performing configuration of
200         //     the context by overriding the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
201         //     method in your derived context.
202         //     If an action is supplied here, the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
203         //     method will still be run if it has been overridden on the derived context. Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
204         //     configuration will be applied in addition to configuration performed here.
205         //     In order for the options to be passed into your context, you need to expose a
206         //     constructor on your context that takes Microsoft.EntityFrameworkCore.DbContextOptions`1
207         //     and passes it to the base constructor of Microsoft.EntityFrameworkCore.DbContext.
208         //
209         //   contextLifetime:
210         //     The lifetime with which to register the DbContext service in the container.
211         //
212         //   optionsLifetime:
213         //     The lifetime with which to register the DbContextOptions service in the container.
214         //
215         // 類型參數:
216         //   TContextService:
217         //     The class or interface that will be used to resolve the context from the container.
218         //
219         //   TContextImplementation:
220         //     The concrete implementation type to create.
221         //
222         // 返回結果:
223         //     The same service collection so that multiple calls can be chained.
224         public static IServiceCollection AddDbContext<TContextService, TContextImplementation>([NotNullAttribute] this IServiceCollection serviceCollection, [CanBeNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService;
225         //
226         // 摘要:
227         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection
228         //     and enables DbContext pooling. Instance pooling can increase throughput in high-scale
229         //     scenarios such as web servers by re-using DbContext instances, rather than creating
230         //     new instances for each request. You use this method when using dependency injection
231         //     in your application, such as with ASP.NET. For more information on setting up
232         //     dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
233         //
234         // 參數:
235         //   serviceCollection:
236         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
237         //     to.
238         //
239         //   optionsAction:
240         //     A required action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
241         //     for the context. When using context pooling, options configuration must be performed
242         //     externally; Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
243         //     will not be called.
244         //
245         //   poolSize:
246         //     Sets the maximum number of instances retained by the pool.
247         //
248         // 類型參數:
249         //   TContext:
250         //     The type of context to be registered.
251         //
252         // 返回結果:
253         //     The same service collection so that multiple calls can be chained.
254         public static IServiceCollection AddDbContextPool<TContext>([NotNullAttribute] this IServiceCollection serviceCollection, [NotNullAttribute] Action<DbContextOptionsBuilder> optionsAction, int poolSize = 128) where TContext : DbContext;
255         //
256         // 摘要:
257         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection
258         //     and enables DbContext pooling. Instance pooling can increase throughput in high-scale
259         //     scenarios such as web servers by re-using DbContext instances, rather than creating
260         //     new instances for each request. You use this method when using dependency injection
261         //     in your application, such as with ASP.NET. For more information on setting up
262         //     dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
263         //
264         // 參數:
265         //   serviceCollection:
266         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
267         //     to.
268         //
269         //   optionsAction:
270         //     A required action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
271         //     for the context. When using context pooling, options configuration must be performed
272         //     externally; Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
273         //     will not be called.
274         //
275         //   poolSize:
276         //     Sets the maximum number of instances retained by the pool.
277         //
278         // 類型參數:
279         //   TContextService:
280         //     The class or interface that will be used to resolve the context from the container.
281         //
282         //   TContextImplementation:
283         //     The concrete implementation type to create.
284         //
285         // 返回結果:
286         //     The same service collection so that multiple calls can be chained.
287         public static IServiceCollection AddDbContextPool<TContextService, TContextImplementation>([NotNullAttribute] this IServiceCollection serviceCollection, [NotNullAttribute] Action<DbContextOptionsBuilder> optionsAction, int poolSize = 128)
288             where TContextService : class
289             where TContextImplementation : DbContext, TContextService;
290         //
291         // 摘要:
292         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection
293         //     and enables DbContext pooling. Instance pooling can increase throughput in high-scale
294         //     scenarios such as web servers by re-using DbContext instances, rather than creating
295         //     new instances for each request. You use this method when using dependency injection
296         //     in your application, such as with ASP.NET. For more information on setting up
297         //     dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
298         //     This overload has an optionsAction that provides the applications System.IServiceProvider.
299         //     This is useful if you want to setup Entity Framework to resolve its internal
300         //     services from the primary application service provider. By default, we recommend
301         //     using the other overload, which allows Entity Framework to create and maintain
302         //     its own System.IServiceProvider for internal Entity Framework services.
303         //
304         // 參數:
305         //   serviceCollection:
306         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
307         //     to.
308         //
309         //   optionsAction:
310         //     A required action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
311         //     for the context. When using context pooling, options configuration must be performed
312         //     externally; Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
313         //     will not be called.
314         //
315         //   poolSize:
316         //     Sets the maximum number of instances retained by the pool.
317         //
318         // 類型參數:
319         //   TContext:
320         //     The type of context to be registered.
321         //
322         // 返回結果:
323         //     The same service collection so that multiple calls can be chained.
324         public static IServiceCollection AddDbContextPool<TContext>([NotNullAttribute] this IServiceCollection serviceCollection, [NotNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction, int poolSize = 128) where TContext : DbContext;
325         //
326         // 摘要:
327         //     Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection
328         //     and enables DbContext pooling. Instance pooling can increase throughput in high-scale
329         //     scenarios such as web servers by re-using DbContext instances, rather than creating
330         //     new instances for each request. You use this method when using dependency injection
331         //     in your application, such as with ASP.NET. For more information on setting up
332         //     dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
333         //     This overload has an optionsAction that provides the applications System.IServiceProvider.
334         //     This is useful if you want to setup Entity Framework to resolve its internal
335         //     services from the primary application service provider. By default, we recommend
336         //     using the other overload, which allows Entity Framework to create and maintain
337         //     its own System.IServiceProvider for internal Entity Framework services.
338         //
339         // 參數:
340         //   serviceCollection:
341         //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
342         //     to.
343         //
344         //   optionsAction:
345         //     A required action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
346         //     for the context. When using context pooling, options configuration must be performed
347         //     externally; Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
348         //     will not be called.
349         //
350         //   poolSize:
351         //     Sets the maximum number of instances retained by the pool.
352         //
353         // 類型參數:
354         //   TContextService:
355         //     The class or interface that will be used to resolve the context from the container.
356         //
357         //   TContextImplementation:
358         //     The concrete implementation type to create.
359         //
360         // 返回結果:
361         //     The same service collection so that multiple calls can be chained.
362         public static IServiceCollection AddDbContextPool<TContextService, TContextImplementation>([NotNullAttribute] this IServiceCollection serviceCollection, [NotNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction, int poolSize = 128)
363             where TContextService : class
364             where TContextImplementation : DbContext, TContextService;
365     }
View Code

 2. 測試案例

  在EF上下文的構造函數中生成一個Guid,如果是單例的,構造函數只會被調用一次,我們通過比較兩個上下文是否相等 或者 比較單次、多次請求中Guid的值是否相同來驗證依賴注入的上下文的各種生命周期。

 1         public EFDB01Context context1;
 2         public EFDB01Context context2;
 3         public FirstController(EFDB01Context db1, EFDB01Context db2)
 4         {
 5             context1 = db1;
 6             context2 = db2;
 7         }
 8         /// <summary>
 9         /// 生命周期測試
10         /// </summary>
11         public IActionResult TestLifeTime()
12         {
13             //測試方法一(判斷兩個上下文是否完全相同)
14             bool isSame1 = object.ReferenceEquals(context1,context2);
15             ViewBag.isSame = isSame1;
16 
17             //測試方法二(通過多次請求來判斷Guid值是否相等)
18             ViewBag.MyGuid1 = context1.myGuid;
19             ViewBag.MyGuid2 = context2.myGuid;
20 
21             return View();
22         }

(1).將參數設置為Singleton: 每次請求的context1和context2的值相等,單次請求和多次請求MyGuid1、MyGuid2的值均相等,從而證明是全局單例的。

(2).將參數設置為Scoped:每次請求的context1和context2的值相等,單次請求中MyGuid1和MyGuid2的值相等,多次請求的情況下,每次產生的MyGuid1之間均不相同, 每次產生的MyGuid2之間均不相同,從而證明是請求內單例的。

(3).將參數設置為Transient:每次請求的context1和context2的值不相等,單次請求中MyGuid1和MyGuid2的值也不相等,多次請求的情況下,每次產生的MyGuid1之間均不相同, 每次產生的MyGuid2之間均不相同,從而證明是瞬時的。

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM