I've just been using the above answers to write a command line program for doing this in c#
and thought I'd expand a bit on the answers above.
if you want to output data as well the schema you need to use:
scripter.EnumScript(something);
//instead of
scripter.Script(something);
The script method just checks for the IncludeData option and throws an exception if it is set, but you have to get on google to find out what the right method to use is! Interesting API design!
The relevant lists in the database are as follows:
database.Tables
database.Schemas
database.Views
database.StoredProcedures
database.UserDefinedFunctions
database.Users
database.Roles
database.Sequences
although that might not be exhaustive.
Getting rid of system objects
The lists in these objects are all custom types which are IEnumerable but not IEnumerable<T>
so you can't do linq on them. This also means you have to to find out what type is in them and use foreach's implicit casts to get them out. I'd never used that in c# before but I guess this stuff is probably targeting framework 2.
A lot of them also have properties called IsSystemObject but this is not implementing an interface. At first it looks like it'll be a real pain to get rid of all the system objects but you can cull them all in one fell swoop by setting the following option:
options.AllowSystemObjects = false;
This works for everything except for Roles for those you have to do the system ones by hand:
foreach (DatabaseRole role in database.Roles)
{
if(role.IsFixedRole)
continue;
list.Add(role);
}
Adding objects for output
The process I used was to create an UrnCollection and then add the different list to the collection. Like this:
var list = new UrnCollection();
foreach (Schema schema in database.Schemas)
list.Add(schema.Urn);
//... more of these
scripter.EnumScript(list);
Options
From there you need to figure out what options to set to recreate the output you need. A few things to bear in mind:
- Indexes, Triggers, Constraints etc are set by options and not treated as first class objects.
- In the UI in SSMS you can't produce sequences at all so expect at least some diffs in your output if you are using these
See this post for more information on how to get foreign keys etc out.
Health warning
I started looking at this as a way to copy a database as I thought backup and restore wouldn't do what I wanted. After going quite a long way down the smo path and running into a lot of problems I had a bit of a re-evaluation and found backup and restore is a lot simpler for that use case.