15

I'm generating sql database script using c# code.

following code works fine for create table but when I try to use scriptOptions.ScriptData = true; it is throwing following exception.

An unhandled exception of type 'Microsoft.SqlServer.Management.Smo.FailedOperationException' occurred in Microsoft.SqlServer.Smo.dll

Additional information: This method does not support scripting data.

code

 public static string ScriptDatabase(string dbConnectionString, string databaseName)
        {

            SqlConnection conn = new SqlConnection(dbConnectionString);
            ServerConnection serverConn = new ServerConnection(conn);
            var server = new Server(serverConn);
            var database = server.Databases[databaseName];

            var scripter = new Scripter(server);
           // I tried this code also       
           // scripter.Options.ScriptData = true;
            ScriptingOptions scriptOptions = new ScriptingOptions();
            scriptOptions.ScriptDrops = false;
            scriptOptions.ScriptData = true;
            scriptOptions.ScriptSchema = true;


            scriptOptions.IncludeIfNotExists = true;
            string scrs = "";
            string tbScr = "";
            foreach (Table myTable in database.Tables)
            {
                /* Generating IF EXISTS and DROP command for tables */
                StringCollection tableScripts = myTable.Script(scriptOptions);
                foreach (string script in tableScripts)
                    scrs += script + "\n\n";

                /* Generating CREATE TABLE command */
                tableScripts = myTable.Script();
                foreach (string script in tableScripts)
                    tbScr += script + "\n\n";
            }
 return (scrs + "\n\n" + tbScr);
}
Pavel Hodek
  • 14,319
  • 3
  • 32
  • 37
Neo
  • 15,491
  • 59
  • 215
  • 405
  • 1
    Try `Scripter.EnumScript(database.Tables)` rather than `Table.Script()` on each individual table. (Disclaimer: not tested.) – Jeroen Mostert May 03 '16 at 11:41
  • @JeroenMostert not working for me may be i'm using wrongly , can you help me in my code.. thanks – Neo May 04 '16 at 04:08

1 Answers1

20

Updated 17-Dec-2019: Check with latest .NET version; Added required References; Clean-up example code; Added sample conn string

Updated 15-Aug-2023: Check with .NET 7.0 version; Added required NuGet packages; Added export View example

The following was tested on:

  • Win 7.0, .NET 4.0, VS 2010, SQL Server 2008R2
  • Win 7.0, .NET 4.6.1, VS 2017, SQL Server 2014
  • Win 11, .NET 7.0 VS 2022, SQL Server 2022

NuGet packages:

  • Microsoft.SqlServer.SqlManagementObjects
  • Microsoft.Data.SqlClient

Required assembly references (for .NET 4.*):

  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Management.Sdk.Sfc
  • Microsoft.SqlServer.Smo

Note: it seems that SMO is not fully implemented for .NET Core framework family. See this question for an example.

I created a simple Console app and called below function.

public static string ScriptDatabase( string dbConnectionString, string databaseName )
{
    SqlConnection conn = new SqlConnection( dbConnectionString );
    ServerConnection serverConn = new ServerConnection( conn );
    var server = new Server( serverConn );
    var database = server.Databases[databaseName];

    var scripter = new Scripter( server );
    scripter.Options.IncludeIfNotExists = true;
    scripter.Options.ScriptSchema = true;
    scripter.Options.ScriptData = true;

    string scrs = "";
    //Script out Tables
    foreach( Table myTable in database.Tables )
    {
        foreach( string s in scripter.EnumScript( new Urn[] { myTable.Urn } ) )
            scrs += s + "\n\n"; ;
    }
    
    //Script out Views
    foreach( View myView in database.Views )
    {
        //Skip system views
        //There is a scripter.Options.AllowSystemObjects = false; setting that does the same but it is glacially slow
        if( myView.IsSystemObject == true ) continue;
        foreach( string s in scripter.EnumScript( new Urn[] { myView.Urn } ) )
            scrs += s + "\n\n";
    }
    
    return ( scrs );
}

Function would be called as follows:

// Connection string for local SQL Server default instance
ScriptDatabase( "Server=.;Database=PlayGround;Trusted_Connection=True;", "PlayGround" );

Note: See this question if you get the following error

"A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)"

Output:

SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tBlah]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[tBlah](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [tID] [varchar](20) COLLATE Latin1_General_CI_AS NULL,
    [Value] [varchar](20) COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY]
END

SET IDENTITY_INSERT [dbo].[tBlah] ON 


INSERT [dbo].[tBlah] ([ID], [tID], [Value]) VALUES (1, N'2', N'1234')

INSERT [dbo].[tBlah] ([ID], [tID], [Value]) VALUES (2, N'2', N'345.6')

MSDN References:

Alex
  • 4,885
  • 3
  • 19
  • 39
  • 1
    @Kiquenet - Does not look like there is a way: https://stackoverflow.com/questions/35358122/using-smo-to-script-partial-data-content-only-rows-matching-a-where-clause – Alex Feb 09 '18 at 00:57
  • `Assemblies and namespaces ? Microsoft.SqlServer.Smo ?` – Kiquenet Feb 09 '18 at 10:50
  • not working, I have tried same code in C# but it's not giving me Data script of insert query – Hardik Masalawala Dec 16 '19 at 08:56
  • @HardikMasalawala, I have re-created solution using latest .NET and it does work. Do you have any data in tables? – Alex Dec 16 '19 at 23:25
  • 1
    Thanks! You saved me! Table.Script did not work for me, but this one with the Scripter works! – Butterfly Mar 02 '21 at 10:00