2013-11-09 3 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, я получаю:

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 Ith сон 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

Спасибо, зная, что это просто факт жизни. Теперь я могу сосредоточиться на разумной реализации ожидания вместо того, чтобы пытаться найти что-то не так с тем, что я делал ... – pwdiener

ответ

0

Вместо потоковой спячки вы могли бы выполнить эту задачу: создать цикл, который ищет созданную базу данных, и петли, пока вы не можете ее найти.

Как найти, если существует база данных: How to check if a database exists in SQL Server?

Для целей исполнения, вы должны поставить таймер (как сон нить) для каждого цикла, вместо поиска непрерывно. Вы сказали, что среднее время составляет 5 секунд, поэтому цикл на каждые 1 или 2 секунды может быть прекрасным!

Смежные вопросы