2012-11-11 3 views
3

SQL Server 2008과 함께 배포 된 SMO 라이브러리를 사용하여 데이터베이스 스키마를 생성하는 프로그램을 만들고 있습니다.SMO 스크립터가 외부 키 헤더를 생성하지 않는 이유는 무엇입니까?

SQL Server Management Studio 출력을 구성 할 때 scripter 출력 코드를 실제로 얻었습니다 모든 것을 출력하지만 한 가지 흥미로운 예외는 있습니다. SSMS와는 달리 맨 아래에 생성하는 외래 키 제약 조건에 대한 주석 헤더를 출력하지 않습니다. 왜이 사람이 알아낼 수 있을까요? 외래 키는 DRI 제약의 범주에 속하는, 때문에 scrp.Options.DriAllConstraints = true;의 스크립트 것을

private void btnExportScript_Click(object sender, EventArgs ea) { 
    Server srv = setupConnection(); 

    // Reference the database 
    if (!srv.Databases.Contains(cbChooseDb.SelectedItem.ToString())) { 
     _utils.ShowError("Couldn't find DB '" + cbChooseDb.SelectedItem.ToString() + "'."); 
     return; 
    } 
    Database db = srv.Databases[cbChooseDb.SelectedItem.ToString()]; 

    StringBuilder builder = new StringBuilder(); 
    try { 
     Scripter scrp = new Scripter(srv); 
     scrp.Options.AppendToFile = false; 
     scrp.Options.ToFileOnly = false; 
     scrp.Options.ScriptDrops = false;    // Don't script DROPs 
     scrp.Options.Indexes = true;     // Include indexes 
     scrp.Options.DriAllConstraints = true;  // Include referential constraints in the script 
     scrp.Options.Triggers = true;     // Include triggers 
     scrp.Options.FullTextIndexes = true;   // Include full text indexes 
     scrp.Options.NonClusteredIndexes = true;  // Include non-clustered indexes 
     scrp.Options.NoCollation = false;    // Include collation 
     scrp.Options.Bindings = true;     // Include bindings 
     scrp.Options.SchemaQualify = true;   // Include schema qualification, eg. [dbo] 
     scrp.Options.IncludeDatabaseContext = false; 
     scrp.Options.AnsiPadding = true; 
     scrp.Options.FullTextStopLists = true; 
     scrp.Options.IncludeIfNotExists = false; 
     scrp.Options.ScriptBatchTerminator = true; 
     scrp.Options.ExtendedProperties = true; 
     scrp.Options.ClusteredIndexes = true; 
     scrp.Options.FullTextCatalogs = true; 
     scrp.Options.SchemaQualifyForeignKeysReferences = true; 
     scrp.Options.XmlIndexes = true; 
     scrp.Options.IncludeHeaders = true; 

     // Prefectching may speed things up 
     scrp.PrefetchObjects = true; 

     var urns = new List<Urn>(); 

     // Iterate through the tables in database and script each one. 
     foreach (Table tb in db.Tables) { 
      if (tb.IsSystemObject == false) { 
       // Table is not a system object, so add it. 
       urns.Add(tb.Urn); 
      } 
     } 

     // Iterate through the views in database and script each one. Display the script. 
     foreach (Microsoft.SqlServer.Management.Smo.View view in db.Views) { 
      if (view.IsSystemObject == false) { 
       // View is not a system object, so add it. 
       urns.Add(view.Urn); 
      } 
     } 

     // Iterate through the stored procedures in database and script each one. Display the script. 
     foreach (StoredProcedure sp in db.StoredProcedures) { 
      if (sp.IsSystemObject == false) { 
       // Procedure is not a system object, so add it. 
       urns.Add(sp.Urn); 
      } 
     } 

     // Start by manually adding DB context 
     builder.AppendLine("USE [" + db.Name + "]"); 
     builder.AppendLine("GO"); 

     System.Collections.Specialized.StringCollection sc = scrp.Script(urns.ToArray()); 
     foreach (string st in sc) { 
      // It seems each string is a sensible batch, and putting GO after it makes it work in tools like SSMS. 
      // Wrapping each string in an 'exec' statement would work better if using SqlCommand to run the script. 
      builder.Append(st.Trim(new char[] { '\r', '\n' }) + "\r\nGO\r\n"); 
     } 
    } 
    catch (Exception ex) { 
     showExceptionError("Couldn't generate script.", ex); 
     return; 
    } 

    try { 
     File.WriteAllText(txtExportToFile.Text, builder.ToString()); 
     _utils.ShowInfo("DB exported to script at: " + txtExportToFile.Text); 
    } 
    catch (Exception ex) { 
     showExceptionError("Couldn't save script file.", ex); 
     return; 
    } 
} 

참고 : 여기에 내 코드입니다.

답변

0

여기 해결책이 있습니다 그것이 하나 항아리를 부여 않다면 어떤 이유로 Can't get EnumScript() to generate constraints

, 그것은 쓰레기통의 목록을 주어 때 Scripter은 DRI 제약 (외래 키 등)를 방출하지 않습니다, 그러나 그것은 의지를 시각. 거기에 속임수는 그들의 조상의 순서로 Urns를 제공하는 것입니다 : 테이블은 제약 조건에 의해 참조되기 전에 정의되어야합니다. 그렇게하기 위해 DependencyWalker을 사용했습니다.

 var urns = new List<Urn>(); 
     Scripter schemaScripter = new Scripter(srv) { Options = schemaOptions }; 
     Scripter insertScripter = new Scripter(srv) { Options = insertOptions }; 
     var dw = new DependencyWalker(srv); 

     foreach (Table t in db.Tables) 
      if (t.IsSystemObject == false) 
       urns.Add(t.Urn); 
     DependencyTree dTree = dw.DiscoverDependencies(urns.ToArray(), true); 
     DependencyCollection dColl = dw.WalkDependencies(dTree); 

     foreach (var d in dColl) 
     { 
      foreach (var s in schemaScripter.Script(new Urn[] { d.Urn })) 
       strings.Add(s); 
      strings.Add("GO"); 
      if (scriptData) 
      { 
       int n = 0; 
       foreach (var i in insertScripter.EnumScript(new Urn[] {d.Urn})) 
       { 
        strings.Add(i); 
        if ((++n) % 100 == 0) 
         strings.Add("GO"); 
       } 
      } 
     } 

참고하십시오 모든 너무 자주 작은 그래서 SSMS 메모리가 부족하지 않는 배치 크기를 유지 "GO"를 추가

는 여기 개요입니다.

관련 문제