某项目进行中,在项目前期数据库访问正常。在项目后期,尤其是演示系统功能时,在操作一段时间后系统出现数据库连接池不够导致数据库连接不成功。
报错信息:
DevExpress.Xpo.DB.Exceptions.UnableToOpenDatabaseException
HResult=0x80131500
Message=无法打开数据库。连接字符串:“data source=192.168.1.202;user id=sa;password=***REMOVED***;initial catalog=Set;Persist Security Info=true;”;错误:'System.InvalidOperationException: 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
在 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
在 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
在 System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
在 System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
在 System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
在 System.Data.SqlClient.SqlConnection.Open()
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase(SqlConnection conn)“
Source=DevExpress.Xpo.v19.1
StackTrace:
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase(SqlConnection conn)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase()
在 DevExpress.Xpo.DB.ConnectionProviderSql..ctor(IDbConnection connection, AutoCreateOption autoCreateOption)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider..ctor(IDbConnection connection, AutoCreateOption autoCreateOption)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateProviderFromString(String connectionString, AutoCreateOption autoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.Xpo.DB.DataStoreBase.QueryDataStore(String providerType, String connectionString, AutoCreateOption defaultAutoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.Xpo.XpoDefault.GetConnectionProvider(String connectionString, AutoCreateOption defaultAutoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.ExpressApp.Xpo.ConnectionStringDataStoreProvider.CreateWorkingStore(IDisposable[]& disposableObjects)
在 DevExpress.ExpressApp.Xpo.XPObjectSpaceProvider.CreateObjectSpace(Func`1 objectSpaceDelegate)
在 DevExpress.ExpressApp.Xpo.XPObjectSpaceProvider.CreateObjectSpace()
在 SuperNest_DB_Test.Form1.button1_Click(Object sender, EventArgs e) 在 C:\Users\DELL\source\repos\SuperNest_DB_Test\SuperNest_DB_Test\Form1.cs 中: 第 52 行
在 System.Windows.Forms.Control.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
在 System.Windows.Forms.Button.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.Run(Form mainForm)
在 SuperNest_DB_Test.Program.Main() 在 C:\Users\DELL\source\repos\SuperNest_DB_Test\SuperNest_DB_Test\Program.cs 中: 第 19 行
此异常最初是在此调用堆栈中引发的:
[外部代码]
内部异常 1:
InvalidOperationException: 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
数据库:MS SQL Server V2012
经过初步分析,在创建XAF XPObjectSpaceProvider 100次之后出现问题。
解决办法:
1、对XPObjectSpaceProvider做全局复用;
2、对XPObjectSpaceProvider每次使用后释放其数据库连接;
具体使用哪个方式,取决项目的特性。
分析代码:
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Xpo;
using DevExpress.Xpo;
using System;
using System.Collections;
using System.Configuration;
using System.Windows.Forms;
using XSToolSet.Module.BusinessObjects;
namespace SuperNest_DB_Test
{
public partial class Form1 : Form
{
String XSXafDBString;
//数据库访问供应商提供者
XPObjectSpaceProvider osProvider;
//数据库的对象空间(每一个)
IObjectSpace objectSpace;//SYS_User
/// <summary>
///
/// </summary>
public Form1()
{
InitializeComponent();
//获取XPO信息源(必带)
XpoTypesInfoHelper.GetXpoTypeInfoSource();
//申明引用的数据对象
XafTypesInfo.Instance.RegisterEntity(typeof(SYS_User));
XafTypesInfo.Instance.RegisterEntity(typeof(SYS_UserRole));
XafTypesInfo.Instance.RegisterEntity(typeof(SYS_Role));
//给XPO的数据对象指定数据库链接字符串
XSXafDBString = ConfigurationManager.ConnectionStrings["Set"].ConnectionString;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0;i<20000;i++)
{
Console.WriteLine($"Create Connect :{i}");
//创建数据库访问
this.osProvider = new XPObjectSpaceProvider(@XSXafDBString, null);
//获取到数据对象
this.objectSpace = osProvider.CreateObjectSpace();
if (objectSpace != null)
{
objectSpace.Dispose();
}
IDataLayer datalayer = osProvider.DataLayer;
if (datalayer.Connection != null)
{
datalayer.Connection.Dispose();
}
if (osProvider != null)
{
osProvider.Dispose();
}
}
MessageBox.Show($"All done!");
}
}
}