在访问以编程方式创建的数据库之前等待

时间:2013-11-09 23:19:04

标签: c# sql sql-server

我正在使用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的睡眠运行它给了我:

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

很抱歉,如果这很长 - 我试图将其剥离到代码的简短版本,以证明我正在做的事情和问题。

1 个答案:

答案 0 :(得分:0)

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

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

出于性能目的,您应该为每个循环放置一个计时器(如线程休眠),而不是连续搜索。你说平均时间是5秒,所以每1s或2s循环可能没问题!