现在在研究使用EF,遇到这个问题感觉不太正常。
问题简述:EF访问数据库,使用SQL Server Profiler监视SQL执行可以看到,是首先Audit Login 然后执行SQL最后Logout,但是我遇到的问题时执行完所有操作然后Dispose上下文,最有一次Login的操作还是没有Logout,只有关闭程序或等待大概6-10分钟才会有Logout。
我就随便写了个控制台程序,使用多线程访问数据代码如下:
namespace ConsoleApplication2 { class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Class { get; set; } public int Height { get; set; } public int Weight { get; set; } public string Description { get; set; } } class MyDbContext : DbContext { public MyDbContext() : base("default") { } public DbSet<Person> Person { get; set; } } class Program { static void Main(string[] args) { List<Task> ts = new List<Task>(); for (int i = 0; i < 2000; i++) { Task task = new Task(() => { //Thread.Sleep(1000); MyDbContext db2 = new MyDbContext(); using (db2) { var res1 = db2.Person.Where(u => u.Id < 10).ToList(); var p = new Person { Name = "ThreadOne", Description = "ThreadOne" }; db2.Person.Add(p); db2.SaveChanges(); //db2.Dispose(); } }); string state = "Complete" + i; task.ContinueWith(u => { Console.WriteLine(state); }); ts.Add(task); } ts.AsParallel<Task>().ForAll(u => { u.Start(); }); Console.ReadKey(); } } }
执行完成,清空监视等了一会在关闭程序,监视到如图结果:
这是怎么回事啊。
把你贴的代码替换为使用 SqlConnection 实现,然后观察监视结果。
虽然你的回答挺气人的,但是经测试,直接使用ADO表现结果是一样的,看来不是EF的错
多次数据库访问共享一个链接来节省资源提高性能很正常,每次访问都连接关闭不合适
我现在是这样一个场景,要用线程池去并行去使用EF访问数据库,但是现在的结果是线程执行结束了,但是还没Logout,这样膨胀会不会造成问题啊,如果不会,为什么?
@蔚蓝世界: 如果你所有数据访问都通过EF做的,就不需要担心,EF自己有自己维护连接的机制,与你是否用线程池没什么关系,分层框架或组件化编程的基本好处
@draculav: 但是多线程使用EF,为了不产生冲突得保证,每个线程共用一个EF上下文,这就造成了使用多个上下文。
而且照理说我执行一段数据操作是:login-> exec...->logout,为什么代码中的查询操作时是这样的,但是添加操作(一段EF操作的最后一个数据操作)没有执行Logout,而且我都把上下文Using起来了,在怎么说释放资源时也应该给SQL Server发送Logout,而实际情况是关闭进程或者超时是菜发送Logout。
会不会膨胀,还需要用测试说话,你搞多点线程,看看会不会出问题了。我想,EF内部可能会自动判断什么时候关闭连接比较合适吧。
如果一个线程会2次logout,200个大概10-12个,1000个大概10-19个,线程多了可能不是一起执行的。
@蔚蓝世界: 这就以为着,没什么太大的影响嘛。你线程执行快,我就不用忙着关闭连接了。空闲了再关。这样程序和数据库压力都不算大。