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