2013-10-01 2 views
2

У меня есть такой код:Подождите базы данных Создания закончить

using (var sqlConnection = new SqlConnection(connectionString)) 
{ 
    sqlConnection.Open(); 
    using (var sqlCommand = new SqlCommand(scriptText, sqlConnection)) 
    { 
    sqlCommand.ExecuteNonQuery(); 
    } 
} 

в первый раз, я называю его, чтобы создать базу данных, затем я формирую строку подключения к этой БД и попытаться сделать некоторые работы (Open работает нормально и говорит, что соединение действительно открыто для этого второго соединения). Но я получаю «существующее соединение было принудительно закрыто удаленным хостом», и я могу видеть журналы sql «Не удалось найти идентификатор базы данных 9. База данных еще не активирована или может быть в процессе перехода». Итак, на самом деле возврат ExecuteNonQuery перед выполнением задания. Конечно, я могу просто спамить его до тех пор, пока ситуация не изменится, но есть ли лучший способ подождать, когда БД будет готова к работе?

+0

ExecuteNonQuery должен ждать, пока он не будет завершен. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx – Shawn

+0

@ Шаун, я так и думал. Кажется, это не так. – aush

+0

Вы уверены, что база данных создается правильно? – Shawn

ответ

2

Этот полный образец работает для меня.

Создает базу данных, создает таблицу, помещает строку в таблицу.

Не уверен, что не так на вашем конце.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlClient; 

namespace GranadaCoder.PlaygroundConsole.SqlStuff 
{ 
    public class SqlPlayground 
    { 

     public static void EntryPointStuff() 
     { 
      string databaseName = "MyFirstDatabaseABC"; 
      string connectionString = string.Empty; 
      string commandText = string.Empty; 
      int returnValue = 0; 
      string msg = string.Empty; 

      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); 
      builder["Initial Catalog"] = "master"; 
      builder["integrated Security"] = true; 
      builder["Server"] = @"MyMachine\MyInstance"; 
      connectionString = builder.ConnectionString; 


      commandText = string.Format("IF EXISTS (Select * from sys.databases where name = N'{0}') DROP DATABASE [{0}]", databaseName); 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 

      commandText = string.Format("IF NOT EXISTS (Select * from sys.databases where name = N'{0}') CREATE DATABASE [{0}]", databaseName); 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 

      /* Change the Catalog */ 
      builder["Initial Catalog"] = databaseName; 
      connectionString = builder.ConnectionString; 


      commandText = "if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategory]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) BEGIN  DROP TABLE [dbo].[CodeCategory]  END "; 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 

      commandText = "CREATE TABLE [dbo].[CodeCategory] ( CodeCategoryKey   [smallint] not null  , CodeCategoryName  varchar(64) not null ) "; 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 


      commandText = "INSERT INTO [dbo].[CodeCategory] ( CodeCategoryKey  , CodeCategoryName ) Select 1001 , 'MyFirstCodeCategory' "; 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 

      commandText = "Select Count(*) from [dbo].[CodeCategory]"; 
      returnValue = RunACommand(connectionString, commandText); 
      msg = string.Format("'{0}', {1}", returnValue, commandText); 
      Console.WriteLine(msg); 

     } 




     private static int RunACommand(string connectionString, string scriptText) 
     { 

      int returnValue = 0; 

      using (var sqlConnection = new SqlConnection(connectionString)) 
      { 
       sqlConnection.Open(); 
       using (var sqlCommand = new SqlCommand(scriptText, sqlConnection)) 
       { 
        returnValue = sqlCommand.ExecuteNonQuery(); 
       } 
       sqlConnection.Close(); 
      } 

      return returnValue; 
     } 






    } 

} 

Это работает для меня (без исключений):

static void Main(string[] args) 
    { 

     try 
     { 

      SqlPlayground.EntryPointStuff(); 

      Console.WriteLine("Press Enter after deleting the database in SSMS manually with 'Close Existing Connections' checked."); 
      Console.ReadLine(); 

      SqlPlayground.EntryPointStuff(); 


     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 


     Console.WriteLine("Pressing Enter To End"); 
     Console.ReadLine(); 

    } 
+0

Обратите внимание, как я меняю «Начальный каталог» после создания базы данных. – granadaCoder

+0

Благодарим вас за ответ. Я попробовал, и это работает. Тем не менее, если я дважды вызываю «EntryPointStuff» и между этими вызовами, я вручную удаляю db с «закрытыми существующими подключениями», я получаю точно такую ​​же проблему, как я объяснил в своем вопросе. Похоже, это на самом деле мой тестовый пример. – aush

+0

Я добавил дополнительную информацию. Я не понимаю поведение, которое вы описываете. – granadaCoder

0

Вы можете заметить эту проблему, если вы делаете еще коснуться сразу (например схему базы данных обновления.) После создания. Ожидание в течение нескольких секунд, похоже, решает проблему.

//wait for database creation 
Thread.Sleep(3000); 
+0

И «3s» официально определен и гарантирован каждой операционной системой, базой данных, сетевой средой и т. Д. Для создания базы данных, правильно? И, конечно же, сегодня мы все очень хорошо знаем, насколько глупы и бесполезны многопоточность и асинхронность, и очень легко убедиться, что какой-то код в вашей программе не будет выполнен, если поток спал. – aush

+0

@aush Я никогда не делал этих претензий. В моем случае не было многопоточности, так что это сработало для меня. Это будет работать в большинстве случаев, но не использовать его для жизненно важных систем :) –

+0

В моем случае добавление 'Thread.Sleep (...)' помогло, но основной причиной было то, что кэшированное сбойное соединение было использовано методом 'SqlConnection.Open()'. Для этой ситуации см. [Ответ на этот вопрос] (https://stackoverflow.com/questions/17569844/connecting-to-newly-created-database-after-previous-connection-error). [Очистка пула с помощью SqlConnection.ClearAllPools()] (https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearallpools (v = vs.110) .aspx) помогло , Зачем тогда ждать, когда-нибудь помогли? Кажется, этого достаточно, чтобы очистить пул автоматически. – flam3

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