)).Wait();
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
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)
5 context1 = db1;
6 context2 = db2;
8 /// <summary>
9 /// 生命周期测试
10 /// </summary>
11 public IActionResult TestLifeTime()
12 {
13 //测试方法一(判断两个上下文是否完全相同)
14 bool isSame1 = object.ReferenceEquals(context1,context2);
15 ViewBag.isSame = isSame1;
17 //测试方法二(通过多次请求来判断Guid值是否相等)
18 ViewBag.MyGuid1 = context1.myGuid;
19 ViewBag.MyGuid2 = context2.myGuid;
21 return View();
(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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。