简介
我正在编写一个Web应用程序(C#/ ASP.NET MVC 3,.NET Framework 4,MS SQL Server 2008,System.Data.ODBC用于数据库连接),我在数据库创建方面遇到了一些问题/删除。
我要求应用程序应该能够创建和删除数据库。
问题
应用程序无法对该功能进行压力测试。更具体地说,如果客户端开始快速创建,删除,再次创建具有相同名称的数据库,则最终(〜第5次请求)服务器代码抛出ODBCException“连接已被禁用。”。在已执行测试的所有计算机上都会观察到此行为 - 确切的失败请求可能不是第5个,而是在该值附近。
研究
谷歌搜索异常给出了非常低的输出 - 异常似乎非常通用,没有发现模拟问题。我发现的一个建议是我的开发Windows 7可能无法处理多个同时连接,因为它不是服务器操作系统。我尝试在Windows 2008 Server上安装我们的应用程序 - 行为几乎没有变化,只是在异常发生之前处理了更多的请求。
有关实施的代码和其他评论
使用以下存储过程创建数据库:
CREATE PROCEDURE [dbo].[sp_DBCreate]
...
@databasename nvarchar(124) -- 124 is max length of database file names
AS
DECLARE @sql nvarchar(150);
BEGIN
...
-- Create a new database
SET @sql = N'CREATE DATABASE ' + quotename(@databasename, '[');
EXEC(@sql);
IF @@ERROR <> 0
RETURN -2;
...
RETURN 0;
END
使用以下SP删除数据库:
CREATE PROCEDURE [dbo].[sp_DomainDelete]
...
@databasename nvarchar(124) -- 124 is max length of database file names
AS
DECLARE @sql nvarchar(200);
BEGIN
...
-- check if database exists
IF EXISTS(SELECT * FROM [sys].[databases] WHERE [name] = @databasename)
BEGIN
-- drop all active connections
SET @sql = N'ALTER DATABASE' + quotename(@databasename, '[') + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE';
EXEC(@sql);
-- Delete database
SET @sql = N'DROP DATABASE ' + quotename(@databasename, '[');
EXEC(@sql);
IF @@ERROR <> 0
RETURN -1; --error deleting database
END
--ELSE database does not exist. consider it deleted.
RETURN 0;
END
在两个SP中,我都跳过了较少相关的部分,例如健全性检查。
我没有使用任何ORM,所有SP都是通过使用OdbcCommand
实例从代码中调用的。为每个函数调用创建新的OdbcConnection
。
我真诚地希望有人能给我这个问题的线索。
UPD :如果我们只是快速创建一堆数据库,就会出现完全相同的问题。感谢大家对数据库删除代码的建议,但我更愿意有一个解决方案或者至少提供一个更普遍的问题的提示 - 即使不删除DB也会出现这个问题。
UPD2 :以下代码用于SP调用:
public static int ExecuteNonQuery(string sql, params object[] parameters)
{
try
{
var command = new OdbcCommand();
Prepare(command, new OdbcConnection( GetConnectionString() /*irrelevant*/), null, CommandType.Text, sql,
parameters == null ?
new List<OdbcParameter>().ToArray() :
parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray());
return command.ExecuteNonQuery();
}
catch (OdbcException ex)
{
// Logging here
throw;
}
}
public static void Prepare(
OdbcCommand command,
OdbcConnection connection,
OdbcTransaction transaction,
CommandType commandType,
string commandText,
params OdbcParameter[] commandParameters)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
command.Connection = connection;
command.CommandText = commandText;
if (transaction != null)
{
command.Transaction = transaction;
}
command.CommandType = commandType;
if (commandParameters != null)
{
command.Parameters.AddRange(
commandParameters.Select(p => p.Value==null &&
p.Direction == ParameterDirection.Input ?
new OdbcParameter(p.ParameterName, DBNull.Value) : p).ToArray());
}
}
示例连接字符串:
Driver={SQL Server}; Server=LOCALHOST;Uid=sa;Pwd=<password here>;
答案 0 :(得分:1)
好。 OdbcConnection可能存在范围问题,但在完成连接后,您似乎也没有关闭连接。这可能意味着您依赖池管理器来关闭未使用的连接,并在它们超时时将它们返回池中。完成后,using
块将自动关闭并处理连接,允许它返回到连接池。
试试这段代码:
public static int ExecuteNonQuery(string sql, params object[] parameters)
{
int result = 0;
try
{
var command = new OdbcCommand();
using (OdbcConnection connection = new OdbcConnection(GetConnectionString() /*irrelevant*/))
{
connection.Open();
Prepare(command, connection, null, CommandType.Text, sql,
parameters == null ?
new List<OdbcParameter>().ToArray() :
parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray());
result = command.ExecuteNonQuery();
}
}
catch (OdbcException ex)
{
// Logging here
throw;
}
return result;
}