我正在写一个Web应用程序(C#/ ASP.NET MVC 3,.NET框架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我跳过了一些不太相关的部分,比如完整性检查。我没有使用任何奥姆斯
,所有SP通过使用OdbcCommand
情况下从代码中调用。每个函数调用都会创建新的OdbcConnection
。
我真诚地希望有人可以给我线索的问题。
UPD:如果我们只是快速创建一堆数据库,就会发生完全相同的问题。感谢大家的建议,在数据库中删除代码,但我宁愿有更普遍的问题的解决方案,或者至少暗示 - 甚至没有出现在所有的删除数据块的一个。
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());
}
}
样品连接字符串:
'WITH ROLLBACK IMMEDIATE' SET SINGLE_USER使用该数据库将杀死其他连接。 – 2011-12-21 11:59:45
@MartinSmith:这实际上是我们想要做的。我们有一些长期的请求,这将使得数据库无法快速删除。虽然我看到你的观点 - 这种说法可能会阻碍连接池的连接,对吧?这可能是导致此类行为的原因......无论如何,即使我们不删除数据库,也存在同样的问题。即使快速添加5个以上的数据库(当然有不同的名称)也会导致相同的结果。 – 2011-12-21 12:05:13
我认为从调用程序接收到此错误消息?您是否检查过连接池是否被禁用? – ChrisBD 2011-12-21 12:17:01