2013-11-09 18 views
2

我正在使用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 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 

运行它w第i个5000的睡眠给了我:

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 

和运行,如果拱数据库已经存在给:

All done 

很抱歉,如果这是长 - 我试图剥离下来到的短版代码将证明我在做什么和问题。

+1

因为这需要多长时间才能清除磁盘上的事务日志(如果没有打开即时数据文件初始化,可能还需要数据文件)。它会根据数据库文件的大小而变化 –

+0

谢谢 - 知道这只是生活中的一个事实。现在我可以专注于一个合理的等待实现,而不是试图找出我正在做的事情有什么问题...... – pwdiener

回答

0

取而代之的是线程睡眠,您可以执行此任务:创建一个搜索创建的数据库的循环,并在找不到时循环。

如何找到如果数据库存在:How to check if a database exists in SQL Server?

出于性能的目的,你应该把一个计时器(比如一个线程睡眠)for each循环,而不是不断地探索。你说平均时间是5秒,所以在1秒或2秒循环可能没问题!

相关问题