一. 配置相關
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 }
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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。