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

标签 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 的 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

很抱歉,如果这很长 - 我试图将其简化为能够演示我正在做的事情和问题的代码的简短版本。

最佳答案

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

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

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

关于c# - 在访问以编程方式创建的数据库之前等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19884357/

相关文章:

c# - 反编译C#时出现"PrivateImplementationDetails"函数

sql - PostgreSQL 高级记录计数

sql - 调试 BigQuery 存储过程

sql-server - 使用 REPAIR_ALLOW_DATA_LOSS 时丢失了哪些(类型)数据?

c# - D3DImage TryLock 失败

c# - Microsoft Graph - 在 SDK C# 中过滤

sql - Rails 3 HABTM 按记录关联模型属性查找

c# - 如何设计规则引擎?

sql-server - 如何在 SQL Server 中应用反向 STUFF

c# - error 42601 语法错误 at or near