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 数据库的情况下运行它时,我得到:

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

对不起,如果这很长 - 我试图将它简化为代码的简短版本,以展示我在做什么和问题。

4

1 回答 1

0

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

如何查找数据库是否存在:如何检查 SQL Server 中是否存在数据库?

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

于 2013-11-10T04:18:38.073 回答