<分区>
我正在使用 SqlClient 在我的程序中创建一个数据库。该应用程序需要定期创建一个新数据库,但结构是相同的。所以我在一个文件中有创建脚本,我一次一行地执行它。完成后,我将其关闭,因为应用程序的另一部分(使用 SubSonic 编写)随后将操作新创建的数据库。
我遇到的问题是,即使在成功创建数据库之后,当我去访问它时,我也会遇到异常,告诉我登录失败。一段时间后,此访问成功。我已将其缩小到 5 秒 - 任何不足都会导致失败,在 5 秒时它工作正常。下面的代码证明了这一点(以一种人为的方式),但它也向我证明了 SubSonic 根本没有涉及该问题。
这是我只需要忍受的事情,还是我做的不对?
我的代码是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace SqlConnTest
{
class Program
{
static void Main(string[] args)
{
var x = new ContentDB();
if (x.IsNew)
{
x.Dispose();
System.Threading.Thread.Sleep(4500);
Console.WriteLine("Second time around");
x = new ContentDB();
}
Console.WriteLine("All done");
Console.ReadKey();
}
}
class ContentDB : IDisposable
{
private bool disposed = false;
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
}
disposed = true;
}
}
public bool IsNew {get;set;}
public ContentDB()
{
SqlConnection conn = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=Arch;Persist Security Info=False;User ID=Brunner;Password=Brunn3r1x");
try
{
conn.Open();
}
catch (SqlException ex)
{
Console.WriteLine("Arch database needs to be created. {0}", ex.Message);
IsNew = true;
}
finally
{
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Dispose();
}
if (IsNew)
CreateDB();
}
private void CreateDB()
{
using (var SqlScriptReader = new StreamReader("c:\\temp\\create.sql"))
{
var conn = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=master;Persist Security Info=False;User ID=Brunner;Password=Brunn3r1x");
conn.Open();
string SqlCmd = SqlScriptReader.ReadLine();
while (SqlCmd != null && SqlCmd != String.Empty)
{
try
{
var cmd = new SqlCommand(SqlCmd,conn);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
catch (SqlException ex)
{
Console.WriteLine("SQL command {0} failed,\n{1}", SqlCmd,ex.Message);
}
SqlCmd = SqlScriptReader.ReadLine();
}
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Dispose();
}
Console.WriteLine("CreateDB finished");
}
}
.SQL 文件的内容是:
USE [master]
CREATE DATABASE [Arch] ON PRIMARY ( NAME = N'Arch', FILENAME = N'C:\temp\Arch.mdf', SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG ON ( NAME = N'Arch_log', FILENAME = N'C:\temp\Arch_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
USE [Arch]
CREATE TABLE [dbo].[RptContent] ([RptContentID] [int] IDENTITY(1,1) NOT NULL, [RptContentBLOB] [varbinary](max) NOT NULL CONSTRAINT [PK_RptContent] PRIMARY KEY CLUSTERED ([RptContentID] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
当我在没有 Arch 数据库的情况下运行它时,我得到:
Arch database needs to be created. Cannot open database "Arch" requested by the
login. The login failed.
Login failed for user 'Brunner'.
CreateDB finished
Second time around
Arch database needs to be created. Cannot open database "Arch" requested by the
login. The login failed.
Login failed for user 'Brunner'.
SQL command CREATE DATABASE [Arch] ON PRIMARY ( NAME = N'Arch', FILENAME = N'C:
\temp\Arch.mdf', SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG
ON ( NAME = N'Arch_log', FILENAME = N'C:\temp\Arch_log.ldf' , SIZE = 1024KB , M
AXSIZE = 2048GB , FILEGROWTH = 10%) failed,
Database 'Arch' already exists. Choose a different database name.
SQL command CREATE TABLE [dbo].[RptContent] ([RptContentID] [int] IDENTIT
Y(1,1) NOT NULL, [RptContentBLOB] [varbinary](max) NOT NULL CONSTRAINT
[PK_RptContent] PRIMARY KEY CLUSTERED ([RptContentID] ASC ) WITH (PAD_INDEX =
OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] failed,
There is already an object named 'RptContent' in the database.
CreateDB finished
All done
以 5000 的 sleep 运行它给我:
Arch database needs to be created. Cannot open database "Arch" requested by the
login. The login failed.
Login failed for user 'Brunner'.
CreateDB finished
Second time around
All done
如果 Arch 数据库已经存在则运行:
All done
很抱歉,如果这很长 - 我试图将其简化为能够演示我正在做的事情和问题的代码的简短版本。