2010-11-23 3 views
0

Все последующей обработки происходит на LocalMachine:метод SqlBulkCopy WriteToServer не писать никаких данных при использовании DataTable

У меня есть база данных источника (на сервере) и базу данных назначения (локальная машина). У меня есть список таблиц, которые я хочу скопировать из источника в пункт назначения, то есть server -> local.

Я начинаю с хранения всех данных с сервера в массиве DataTable с использованием простых операторов SELECT * и использования Adpter.Fill (myDataTable), а затем добавления myDataTable в массив DataTable.

Затем локально я запускаю SQL-скрипт, который у меня есть на диске, чтобы удалить локальную базу данных и воссоздать ее. Получил скрипт из SSMS с помощью [RightClick -> Tasks -> Generate Scripts]

После удаления и воссоздания локальной базы данных я использовал SqlBulkCopy с ранее установленным массивом DataTable для копирования данных сервера во вновь созданную локальную базу данных.


Проблема в том, что все работает так, как ожидается, пока я не удалю часть SqlBulkCopy. Я не получаю никаких исключений, сообщений и никаких bcp_SqlRowsCopied событий, которые срабатывают. Данные просто не копируются ... Что здесь происходит, я бы по крайней мере ожидать какой-то ошибки ...


Вот код для консольного приложения в полном комплекте: Обратите внимание, что он не готов к производству, поскольку до сих пор нет обработки ошибок.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Data; 
using System.IO; 
using System.Diagnostics; 

namespace TomboDBSync 
{ 
    class Program 
    { 
     //Names of all the tables to copy from the server (the source) to our local db (the destination) 
     public static string[] tables = new string[] {"br_Make_Model", "br_Model_Series", "br_Product_EngineCapacity", "br_Product_ProductAttributeDescription", "CompanyPassword", "dtproperties", "EngineCapacity", "Make", "Model", "PetrolType", "Product", "ProductAttribute", "ProductAttributeDescription", "ProductsImport", "ProductType", "Role", "SearchString", "Series", "Supplier", "Tally", "Transmission", "Users", "Year", "GRV"}; 


     static void Main(string[] args) 
     { 
      //Get Data from SourceDB 
      DataTable[] dtTables = GetDataTables(tables); 

      //Drop and Recreate Destination DB using SQL scripts 
      DropAndRecreateDB(); 

      //Populate Destination with Data from SourceDB DataTables 
      InsertDataFromDataTables(dtTables); 
     } 

     /// <summary> 
     /// Takes all the data in the dtTables array which we got from the server (the source) and 
     /// Bulk Copy it all into the local database (the destination) 
     /// </summary> 
     /// <param name="dtTables"></param> 
     private static void InsertDataFromDataTables(DataTable[] dtTables) 
     { 
      foreach (DataTable dtTable in dtTables.ToList<DataTable>()) 
      { 
       using (SqlBulkCopy bcp = new SqlBulkCopy(getLocalConnectionString(), SqlBulkCopyOptions.KeepIdentity & SqlBulkCopyOptions.KeepNulls)) 
       { 
        bcp.DestinationTableName = dtTable.TableName; 

        bcp.SqlRowsCopied += new SqlRowsCopiedEventHandler(bcp_SqlRowsCopied); 
        for (int colIndex = 0; colIndex < dtTable.Columns.Count; colIndex++) 
        { 
         bcp.ColumnMappings.Add(colIndex, colIndex); 
        } 
        bcp.WriteToServer(dtTable); 

       } 
      }      
     } 


     /// <summary> 
     /// Row Copied eEvent handler for SqlBulkCopy 
     /// </summary> 
     static void bcp_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) 
     { 
      Console.WriteLine("row written"); 
     } 

     /// <summary> 
     /// 1) Takes a list of tablenames. 
     /// 2) Connects to the server (the source) 
     /// 3) Does a SELECT * on all the tables and stick the results into DataTables 
     /// </summary> 
     /// <param name="tables"></param> 
     /// <returns>Returns an array of DataTables with all the data from the server in them</returns> 
     public static DataTable[] GetDataTables(string[] tables) 
     {    
      //Query all the server tables and stick 'em into DataTables   
      DataTable[] dataTables = new DataTable[tables.Length]; 

      for (int tableIndex = 0; tableIndex < tables.Length; tableIndex++) 
      { 
       string qry = "SELECT * FROM " + tables[tableIndex] + ";"; 
       Console.Write(qry); 
       DataTable dtTable = new DataTable(); 

       using (SqlConnection connection = new SqlConnection(getServerConnectionString())) 
       { 
        if (connection.State != ConnectionState.Open) connection.Open(); 
        using (SqlCommand cmd = new SqlCommand(qry, connection)) 
        { 
         SqlDataAdapter adapter = new SqlDataAdapter(); 
         adapter.SelectCommand = cmd; 
         adapter.Fill(dtTable); 
        } 
       } 
       dtTable.TableName = tables[tableIndex]; 
       dataTables[tableIndex] = dtTable; 
       Console.WriteLine(" Rows: " + dtTable.Rows.Count); 
      } 
      return dataTables; 
     } 


     /// <summary> 
     /// Parses and executes the script needed to drop and recreate the database 
     /// </summary> 
     private static void DropAndRecreateDB() 
     { 
      using (SqlConnection connection = new SqlConnection(getLocalConnectionString())) 
      { 
       string[] queries = getDropAndRecreateScript().Split(new string[] { "GO\r\n", "GO ", "GO\t" }, StringSplitOptions.RemoveEmptyEntries); 
       foreach (string qry in queries) 
       { 
        if (connection.State != ConnectionState.Open) connection.Open(); 
        using (SqlCommand cmd = new SqlCommand(qry, connection)) 
        { 
         cmd.ExecuteNonQuery(); 
        } 
       } 
      } 
     } 

     /// <summary> 
     /// Reads in the createdbscript.sql file from disk. 
     /// It contains all the SQL statements needed to drop and recreate the database. 
     /// </summary> 
     /// <returns>SQL to drop and recreate the database</returns> 

     public static string getDropAndRecreateScript() 
     { 
      string qry = ""; 
      StreamReader re = File.OpenText("createdbscript.sql"); 
      string input = null; 
      while ((input = re.ReadLine()) != null) 
      { 
       qry += (" " + input + "\r\n"); 
      } 
      Console.WriteLine(qry); 
      re.Close(); 
      return qry; 
     } 

     public static string getServerConnectionString() 
     { 
      return ConfigurationManager.AppSettings["SOURCEDB"]; 
     } 

     public static string getLocalConnectionString() 
     { 
      return ConfigurationManager.AppSettings["DESTINATIONDB"]; 
     } 

    } 
} 
+0

Это странно. Когда я запускаю свой код, я заполняю таблицы, но я не получаю никаких событий. Является ли ваш сценарий создания просто связкой однострочных операторов «DROP TABLE xxxx», «CREATE TABLE xxxx (...)»? Можете ли вы опубликовать несколько строк контекста из своей БД и строки подключения? – Matt 2010-11-23 15:05:45

ответ

5

Я пробовал свой код и успешно копирует таблицы для меня!

Для того, чтобы получить событие SqlRowsCopied, необходимо установить bcp.NotifyAfter в значение> 0.

Что касается того, почему вы не видите значения, я не совсем уверен. Если БД или таблицы там нет, вы получите исключение (или, по крайней мере, я сделал). Одно из отличий в моем коде заключается в том, что я прокомментировал DropAndRecreateDB() и, когда я ударил эту точку в отладчике, я вручную выполнил сценарий создания сбрасывания вручную в SQL и проверил, что таблицы присутствуют.

Поскольку ваш фактический код копирования работает отлично для меня, как вы его разместили, я бы дважды проверял, чтобы ваши строки подключения были такими, какие вы думаете. Если бы вы могли опубликовать эту информацию, было бы легче продолжить отслеживание.

Update:

FWIW, вот мое падение/создать скрипт:

USE [master]; 
ALTER DATABASE MyTestDB2 SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 
DROP DATABASE MyTestDB2; 
GO 
CREATE DATABASE MyTestDB2; 
GO 

USE [MyTestDB2]; 

CREATE TABLE [dbo].[tblPetTypes](
    [commonname] [nvarchar](50) NOT NULL, 
    PRIMARY KEY CLUSTERED ([commonname]) 
) 

CREATE TABLE [dbo].[tblPeople](
    [oid] [int] IDENTITY(1,1) NOT NULL, 
    [firstname] [nvarchar](30) NOT NULL, 
    [lastname] [nvarchar](30) NOT NULL, 
    [phone] [nvarchar](30) NULL, 
    PRIMARY KEY CLUSTERED ([oid]) 
) 

CREATE TABLE [dbo].[tblPets](
    [oid] [int] IDENTITY(1,1) NOT NULL, 
    [name] [nvarchar](50) NOT NULL, 
    [pettype] [nvarchar](50) NULL, 
    [ownerid] [int] NULL, 
    PRIMARY KEY CLUSTERED ([oid]) 
) ON [PRIMARY] 

... и я скопировал из MyTestDB в MyTestDB2 на том же сервере.

+0

Привет, Мэтт, спасибо, что на самом деле он тестировал его на вашей стороне. Я чувствую себя абсолютным dunce, я смотрел на неправильную базу данных на коробке:/Идти сидеть в углу сейчас и размышлять о моей карьере :) Я дал вам ответы на ответы, так как он правильно указал, что код делает в факт работы. – n4rzul 2010-11-25 07:25:57

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