このコードサンプルを検討してください。
var sourceDatabaseConnectionString = "Data Source=MyServer;Initial Catalog=MyDatabase;User Id=MyLogin;Password=MyPassword";
var serverConnection = new ServerConnection
{
ConnectionString = sourceDatabaseConnectionString
};
var server = new Server(serverConnection);
var builder = new SqlConnectionStringBuilder(sourceDatabaseConnectionString);
var database = server.Databases[builder.InitialCatalog];
var transfer = new Transfer(database);
// setting transfer options
transfer.CopyAllObjects = true;
transfer.CopyAllSynonyms = true;
transfer.CopyData = false;
transfer.Options.WithDependencies = true;
transfer.Options.DriAll = true;
transfer.Options.Triggers = true;
transfer.Options.Indexes = true;
transfer.Options.SchemaQualifyForeignKeysReferences = true;
transfer.Options.ExtendedProperties = true;
transfer.Options.IncludeDatabaseRoleMemberships = true;
transfer.Options.Permissions = true;
transfer.PreserveDbo = true;
// scripting database
var script = transfer.ScriptTransfer();
既存のデータベースから空白を取得しようとします。
このデータベースの一部のオブジェクトは、リンクサーバーにあるオブジェクトに依存しています。このコードがそのようなオブジェクトのスクリプトを作成しようとすると、ScriptTransfer
は「ユーザー 'MyLogin'のログインに失敗しました」で失敗します。
ログ分析によると、MyLogin
がいいねしたサーバーにログインしようとするとエラーが発生します。しかし、これの必要性は何ですか?結局のところ、私はMyDatabase
のCREATE ...
スクリプトの束を取得したいだけで、リンクされたサーバーからデータを読み取りたくありません。
私のSQLServerとSMOのバージョンは2012SP1です。
ログインしているSQLServerからのみデータを取得できます。テーブル定義、ストアドプロシージャなどのメタデータもデータです。
したがって、リンクサーバーを介したログインは成功する必要があります。これは、他のサーバーへのログイン権限を付与することで実行できます。または、リンクサーバーのセキュリティは、必要な権限を持つ特定のログインを介して行うことができます。
ただし、データベースのメタデータに対する権限を取得する意味するものではありませんデータベース内のデータに対する権限が必要であること。例えば:
USE DBName;
GRANT VIEW DEFINITION ON DATABASE::DBName TO [YourDomain\YourLogin]
これにより、ユーザーデータにアクセスしなくても、データベースから定義をスクリプト化できます。 (ただし、必要に応じて個別に付与することもできます。)
編集:SQL Serverは、リンクサーバー全体での遅延名前解決をサポートしていません。したがって、リモートテーブルへの参照を解決できないため、スクリプトが失敗していると確信しています。
もちろん、ストアドプロシージャが暗号化されていない場合、テキストはローカルサーバーのsys.sql_modulesに格納されます。そこからテキストを抽出できます。
SELECT definition FROM DBName.sys.sql_modules
WHERE object_id = object_id(N'DBName.Schema.ObjectName');