6

Podczas publikowania dakpac za pomocą programu sqlpackage.exe, uruchamia najpierw Schema Compare, a następnie skrypty przed wdrożeniem. Powoduje to problem, gdy na przykład trzeba upuścić tabelę lub zmienić nazwę kolumny. Porównanie schematu zostało wykonane przed modyfikacją obiektu i niepowodzeniem wdrożenia. Opublikuj należy powtórzyć, aby uwzględnić nowy schemat.Schema porównuje biegi przed skryptami przed wdrożeniem podczas publikowania

Ktoś ma do tego zadanie, które nie wymaga podwójnego publikowania?

+0

Zmiana nazwy powinna odbywać się w trybie natywnym, jeśli używana jest funkcja Refactor. Zrzucanie tabel jest również obsługiwane w projekcie. Jednak sugestia Ed jest ważna w czasach, gdy natywna funkcjonalność nie będzie działać. Co próbujesz upuścić/zmienić nazwę/osiągnąć, co należy zrobić przed porównaniem schematu? –

+0

W tym konkretnym przypadku upuszczam klucz obcy zmieniający kolumnę FK z BIGINT na INT i wskazując FK na inną tabelę, która sama jest ponownie uwzględniana. Wdrożenie nie powiedzie się po pierwszym uruchomieniu, ponieważ porównywanie schematu jest wykonywane przed tymi zmianami. Rozmieszcza się przy drugim uruchomieniu. – Metaphor

Odpowiedz

4

Gert Drapers nazwał go jako Pre -pre Deployment skrypt here

W rzeczywistości jest to wyzwanie. Jeśli musisz dodać kolumnę nie-nullable i klucz obcy do tabeli pełnej danych - możesz to zrobić tylko za pomocą oddzielnego skryptu.

Jeśli jesteś jedynym programistą - to nie jest problem, ale gdy masz duży zespół, "oddzielny skrypt" musi zostać jakoś wykonany przed opublikowaniem każdego DB.

Obejście użyliśmy:

  • Tworzenie osobnego SQL "Przed publikuje" skryptu (w projekcie DB), który ma właściwość [Zbuduj action = BRAK]
  • Tworzenie custom MSBuild Task gdzie zadzwonić SQLCMD.EXE narzędzie przekazujące skrypt "Przed opublikowaniem" jako parametr, a następnie wywołanie narzędzia SQLPACKAGE.EXE przekazującego DB.dacpac
  • Dodanie wywołania niestandardowego zadania MSBuild do pliku db.sqlproj. Na przykład:
<UsingTask 
     TaskName="MSBuild.MsSql.DeployTask" 
     AssemblyFile="$(MSBuildProjectDirectory)\Deploy\MsBuild.MsSql.DeployTask.dll" /> 

<Target Name="AfterBuild"> 
    <DeployTask 
     Configuration="$(Configuration)" 
     DeployConfigPath="$(MSBuildProjectDirectory)\Deploy\Deploy.config" 
     ProjectDirectory="$(MSBuildProjectDirectory)" 
     OutputDirectory="$(OutputPath)" 
     DacVersion="$(DacVersion)"> 
    </DeployTask> 
</Target> 

MsBuild.MsSql.DeployTask.dll powyżej jest to, że zwyczaj MSBuild Task.

W ten sposób skrypt "Przed opublikowaniem" mógł zostać wywołany z Visual Studio.

Dla CI użyliśmy pliku wsadowego (* .bat), w którym wywołano te same dwa narzędzia (SQLCMD.EXE: & SQLPACKAGE.EXE).

Ostateczny proces mamy to trochę skomplikowane i powinny zostać opisane w osobnym artykule - tutaj wspominałem kierunek tylko :)

1

stanęliśmy sytuacji, kiedy musimy przekształcić dane z jednej tabeli w inne podczas wdrażania projektu bazy danych. Oczywiście problemem jest korzystanie z projektu bazy danych, ponieważ w fazie przedinstalacyjnej tabela docelowa (kolumna) nadal nie istnieje, ale w skrypcie po wdrożeniu tabela źródłowa (kolumna) jest już nieobecna.

Aby przekształcić dane z TableA do TableB użyliśmy następujące pojęcia (To podejście może być stosowany do wszelkich modyfikacji danych):

  1. Developer dodaje tabeli docelowej (dbo.Tabela B) do projektu DB i wdraża go w lokalnej bazie danych (bez wykonywania usługi SVN).
  2. Tworzy skrypt transformacji przed rozmieszczeniem. Sztuczka polega na tym, że skrypt umieścił dane wynikowe w tabeli tymczasowej: #TableB
  3. Deweloper usuwa dbo.TableA w projekcie DB. Zakłada się, że tabela zostanie usunięta podczas wykonywania głównego wygenerowanego skryptu.
  4. Deweloper pisze skrypt po wdrożeniu, który kopiuje formularz danych # TableB do dbo.TableB, który został właśnie utworzony przez główny skrypt.
  5. Wszystkie zmiany zostały zatwierdzone w SVN.

W ten sposób nie potrzebujemy skryptu sprzed złożenia, ponieważ przechowujemy dane pośrednie w tabeli tymczasowej.

Chciałbym powiedzieć, że podejście, które używa skryptu sprzed złożenia wstępnego, zawierało te same dane pośrednie (tymczasowe), jednak nie jest przechowywane w tabelach tymczasowych, ale w rzeczywistych tabelach. Dzieje się to między wstępnym wdrożeniem a wstępnym wdrożeniem. Po wykonaniu skryptu pre-deployment dane pośrednie znikają.

Co więcej, podejście z wykorzystaniem tabel tymczasowych pozwala nam zmierzyć się następujące skomplikowany ale rzeczywistą sytuację: Wyobraźmy sobie, że mamy dwie przemiany w naszym projekcie DB:

  1. TABLEA -> TableB
  2. TableB -> TableC

Oprócz tego mamy dwie bazy danych:

  1. DatabaeA, które mają tablicę danych, gdzie Tabela A została już przekształcona w TableB. Tabela A jest nieobecna w DatabaseB.

Mimo to możemy poradzić sobie z taką sytuacją. Potrzebujemy tylko jednej nowej akcji przed rozmieszczeniem. Przed transformacją próbujemy skopiować dane z dbo.TableA do #TableA. A skrypt transformacji działa tylko z tabelami tymczasowymi.

Pozwól mi pokazać, jak ten pomysł działa w DatabaseA i DatabaseB. Zakłada się, że projekt DB ma dwie pary skryptów przed i po instalacji: "TableA -> TableB" i "TableB -> TableC".

Poniżej znajduje się przykład skryptów dla transformacji "TableB -> TableC".

przedwdrożeniowa skrypt skrypt

----[The data preparation block]--- 
--We must prepare to possible transformation 
--The condition should verufy the existance of necessary columns 
IF OBJECT_ID('dbo.TableB') IS NOT NULL AND 
    OBJECT_ID('tempdb..#TableB') IS NULL 
BEGIN 
    CREATE TABLE #TableB 
    (
     [Id] INT NOT NULL PRIMARY KEY, 
     [Value1] VARCHAR(50) NULL, 
     [Value2] VARCHAR(50) NULL 
    ) 

    INSERT INTO [#TableB] 
    SELECT [Id], [Value1], [Value2] 
    FROM dbo.TableB 
END 

----[The data transformation block]--- 
--The condition of the transformation start 
--It is very important. It must be as strict as posible to ward off wrong executions. 
--The condition should verufy the existance of necessary columns 
--Note that the condition and the transformation must use the #TableA instead of dbo.TableA 
IF OBJECT_ID('tempdb..#TableB') IS NOT NULL 
BEGIN 

    CREATE TABLE [#TableC] 
    (
     [Id] INT NOT NULL PRIMARY KEY, 
     [Value] VARCHAR(50) NULL 
    ) 

    --Data transformation. The source and destimation tables must be temporary tables. 
    INSERT INTO [#TableC] 
    SELECT [Id], Value1 + ' '+ Value2 as Value 
    FROM [#TableB] 

END 

po wysunięciu

W DatabaseA skrypt pre-rozmieszczenia już stworzył #TableA. Dlatego blok przygotowania danych nie zostanie wykonany, ponieważ w bazie danych nie ma dbo.TableB. Jednak transformacja danych zostanie wykonana, ponieważ istnieje #TableA w bazie danych, która została utworzona przez blok transformacji "TableA -> TableB".

W DatabaseB bloki przygotowania i transformacji danych dla skryptu "TableA -> TableB" nie zostaną wykonane. Jednak mamy już przekształcone dane w dbo.TableB. W związku z tym bloki przygotowania i transformacji danych dla "TableB -> TableC" zostaną wykonane bez żadnego problemu.