使用SMO复制数据库和数据

我试图将数据库的副本复制到同一服务器上的新数据库。 服务器是我在Windows XP下运行SQL 2008 Express的本地计算机。 使用SMO.Transfer类这样做应该很容易,它几乎可以正常工作!

我的代码如下(稍微简化):

Server server = new Server("server"); Database sourceDatabase = server.Databases["source database"]; Database newDatbase = new Database(server, "new name"); newDatbase.Create(); Transfer transfer = new Transfer(sourceDatabase); transfer.CopyAllObjects = true; transfer.Options.WithDependencies = true; transfer.DestinationDatabase = newDatbase.Name; transfer.CopySchema = true; transfer.CopyData = true; StringCollection transferScript = transfer.ScriptTransfer(); using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); using (SqlCommand switchDatabase = new SqlCommand("USE " + newDatbase.Name, conn)) { switchDatabase.ExecuteNonQuery(); } foreach (string scriptLine in transferScript) { using (SqlCommand scriptCmd = new SqlCommand(scriptLine, conn, transaction)) { int res = scriptCmd.ExecuteNonQuery(); } } } 

我在这里做的是首先创建一个新数据库,然后使用Transfer类生成一个复制脚本,最后在新数据库中运行该脚本。

这适用于复制结构,但CopyData选项不起作用!

CopyData选项是否有任何未记录的限制? 该文档仅说该选项指定是否复制数据。

我尝试使用TransferData()方法复制数据库而不使用脚本,但后来我得到一个exception,说“连接到服务器失败”,内部exception显示“建立时出现网络相关或特定于实例的错误”与SQL Server的连接。找不到服务器或无法访问服务器。validation实例名称是否正确以及SQL Server是否配置为允许远程连接。(提供程序:命名管道提供程序,错误:40 – 无法打开连接到SQL Server)“

我也尝试在服务器上启用命名管道,但这没有帮助。

编辑:我找到了一个解决方案,通过进行备份然后将其还原到新数据库。 虽然它很笨拙,而且比它应该慢,所以我仍然在寻找更好的解决方案。

好吧,在联系Microsft支持后,我让它正常工作,但它很慢,或多或少都没用。 执行备份然后还原要快得多,只要新副本与原始副本存在于同一服务器上,我就会使用它。

工作代码如下:

 ServerConnection conn = new ServerConnection("rune\\sql2008"); Server server = new Server(conn); Database newdb = new Database(server, "new database"); newdb.Create(); Transfer transfer = new Transfer(server.Databases["source database"]); transfer.CopyAllObjects = true; transfer.CopyAllUsers = true; transfer.Options.WithDependencies = true; transfer.DestinationDatabase = newdb.Name; transfer.DestinationServer = server.Name; transfer.DestinationLoginSecure = true; transfer.CopySchema = true; transfer.CopyData = true; transfer.Options.ContinueScriptingOnError = true; transfer.TransferData(); 

诀窍是设置DestinationDatabase属性。 即使目标与源相同,也必须设置此项。 此外,我必须作为命名实例连接到服务器,而不是使用其他连接选项。

我得到了这个工作,并提出了一个不使用Transfer类的答案。 这是我使用的方法:

  public bool CreateScript(string oldDatabase, string newDatabase) { SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=" + newDatabase + ";User Id=sa;Password=sa;"); try { Server sv = new Server(); Database db = sv.Databases[oldDatabase]; Database newDatbase = new Database(sv, newDatabase); newDatbase.Create(); ScriptingOptions options = new ScriptingOptions(); StringBuilder sb = new StringBuilder(); options.ScriptData = true; options.ScriptDrops = false; options.ScriptSchema = true; options.EnforceScriptingOptions = true; options.Indexes = true; options.IncludeHeaders = true; options.WithDependencies = true; TableCollection tables = db.Tables; conn.Open(); foreach (Table mytable in tables) { foreach (string line in db.Tables[mytable.Name].EnumScript(options)) { sb.Append(line + "\r\n"); } } string[] splitter = new string[] { "\r\nGO\r\n" }; string[] commandTexts = sb.ToString().Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string command in commandTexts) { SqlCommand comm = new SqlCommand(command, conn); comm.ExecuteNonQuery(); } return true; } catch (Exception e) { System.Diagnostics.Debug.WriteLine("PROGRAM FAILED: " + e.Message); return false; } finally { conn.Close(); } } 

尝试在Server对象上将SetDefaultInitFields设置为true。

我遇到了与SMO数据库对象运行缓慢相同的问题。 我想这是因为sql server不喜欢一次检索整个对象和集合,而是懒得加载所有内容,导致每个字段的往返,这对整个数据库来说效率很低。

这是我的解决方案:

  1. 我有一个名为Olddatabase的数据库
  2. 我将它备份到E:\ databackup \ Old.bak

  3. 如果要在名为NewDatabase的同一服务器中从Olddatabase创建重复数据库

3.1您可以在查询工具中使用命令:EXEC OldDatabase.dbo.sp_helpfile; 如果要将NewDatabase保存在同一文件夹中,则存储确定OldDatabase的路径。

或者您可以将NewDatabase保存在所需的新路径中

  1. 在查询工具中使用此命令

    RESTORE DATABASE NewDatabase FROM DISK =’E:\ databackup \ Old.bak’WOR MOVE’OldDatabase’TO’E:\ New path(或相同路径)\ NewDatabase_Data.mdf’,MOVE’OldDatabase_log’TO’E:\ New路径(或相同的路径)\ NewDatabase_Log.ldf’;

注意:您可以在c#中使用以下命令obove:在sql中创建包含Above命令的Store过程。 你可以用C#调用商店程序