web-dev-qa-db-ja.com

SSDTおよびVisual Studio 2012データベースプロジェクトを使用してデータベースの展開を適切に管理する方法

私は、2012年のデータベースプロジェクトを既存の小規模プロジェクトに採用しようとしている研究段階です。私はDBAではなくC#開発者であるため、ベストプラクティスに特に堪能ではありません。 googleとstackoverflowを数時間検索してきましたが、いくつかの主要な展開シナリオを適切に処理する方法がまだわかりません。

1)いくつかの開発サイクルの過程で、データベースの複数のバージョンをどのように管理しますか?データベースのv3にクライアントがあり、それらをv8にアップグレードしたい場合、どのように管理しますか?現在、製品のすべてのバージョンの手作りのスキーマとデータ移行スクリプトを管理しています。まだこれを個別に行う必要がありますか、またはこれをサポートまたは置換する新しいパラダイムに何かがありますか?

2)データを移動する必要があるような方法でスキーマが変更された場合、これを処理する最良の方法は何ですか?データを保持するために、展開前のスクリプトでいくつかの作業が行われ、展開後のスクリプトによって適切な場所に戻されると想定しています。それはそれの方法ですか、それとももっと良いものがありますか?

3)これらの新しいテクノロジーを使用する最善の方法に関するその他のアドバイスやガイダンスも大歓迎です!

PDATE:この質問を最初に聞いてから、問題に対する私の理解が少し増えました。実行可能な解決策を思いつきましたが、それは期待した解決策ではありませんでした。ここに私の問題の言い換えがあります:

私が抱えている問題は、純粋にデータに関連しています。アプリケーションのバージョン1にクライアントがあり、アプリケーションのバージョン5にアップグレードしたい場合、データベースにデータがなくても問題はありません。 SSDTにインテリジェントにスキーマを比較させ、データベースを一気に移行させただけです。残念ながら、クライアントにはデータがあるため、それほど単純ではありません。アプリケーションのバージョン1からバージョン2からバージョン3(など)へのスキーマの変更はすべて、データに影響します。データを管理するための私の現在の戦略では、各バージョンアップグレード(1から2、2から3など)ごとにスクリプトを維持する必要があります。これにより、アプリケーションのバージョン1からバージョン5に直接移行することができなくなります。なぜなら、そこに直接移行するデータ移行スクリプトがないからです。すべてのクライアントのカスタムアップグレードスクリプトを作成したり、アップグレードスクリプトを管理してすべてのバージョンからすべてのより大きなバージョンに移行したりする見込みは、指数関数的に管理できません。私が望んでいたのは、物事のデータ側をより簡単に、おそらくは物事のスキーマ側と同じくらい簡単に管理できるSSDTが可能にする何らかの戦略があることでした。 SSDTでの最近の経験では、このような戦略が存在するという希望はありませんでしたが、別の方法で見つけたいと思います。

60
Charles Josephs

私はこれに自分で取り組んできましたが、簡単ではないことを伝えられます。

まず、JTによる応答に対処するために、SSDTが持つ宣言的な更新メカニズムであっても、「バージョン」を却下することはできません。 SSDTは、ソーススキーマをターゲットスキーマに移動する「かなり適切な」ジョブ(すべてのスイッチと落とし穴を知っている場合)を実行します。これは、それ自体がバージョン管理を必要としないことは事実ですが、管理方法はわかりません。データの動き」(少なくとも私が見ることができるということではない!)。したがって、DBProjと同様に、事前/事後スクリプトで独自のデバイスに任せました。データモーションスクリプトは既知の開始および終了スキーマ状態に依存するため、DBのバージョン管理を避けることはできません。したがって、「データモーション」スクリプトはスキーマのバージョン付きスナップショットに適用する必要があります。つまり、DBをv1からv8に任意に更新し、データモーションスクリプトv2からv8が機能することを期待できません(おそらく、 v1データモーションスクリプトが必要です)。

悲しいことに、SSDTの公開には、このシナリオを統合的な方法で処理できるメカニズムはありません。つまり、独自のスキャフォールディングを追加する必要があります。

最初のトリックは、データベース(およびSSDTプロジェクト)内のバージョンを追跡することです。 DBProjでトリックを使い始め、それをSSDTに持ち込みました。いくつかの調査を行った結果、他の人もこれを使用していることがわかりました。データベース自体にDB拡張プロパティを適用し(「BuildVersion」または「AppVersion」など)、バージョン値を適用できます。その後、SSDTプロジェクト自体でこの拡張プロパティをキャプチャすると、SSDTがスクリプトとして追加します(拡張プロパティを含む発行オプションを確認できます)。次に、SQLCMD変数を使用して、現在のパスで適用されているソースバージョンとターゲットバージョンを識別します。ソース(プロジェクトのスナップショット)とターゲット(更新されるターゲットdb)の間のバージョンのデルタを特定すると、適用する必要があるすべてのスナップショットを見つけることができます。残念ながら、これはinside SSDT展開から行うのが難しいため、おそらくビルドまたは展開パイプラインに移動する必要があります(TFS自動展開を使用し、これを行うカスタムアクションがあります)。

次のハードルは、スキーマのスナップショットとそれに関連するデータモーションスクリプトを保持することです。この場合、スクリプトを可能な限りべき等性にすることが役立ちます(つまり、有害な副作用なしにスクリプトを再実行できます)。 1回だけ実行する必要があるスクリプトから安全に再実行できるスクリプトを分割するのに役立ちます。静的参照データ(ディクショナリまたはルックアップテーブル)でも同じことを実行しています。つまり、参照データの同期を維持するMERGEスクリプトのライブラリ(テーブルごとに1つ)があり、これらのスクリプトは投稿に含まれています-展開スクリプト(SQLCMD:rコマンドを使用)。ここで重要なことは、これらの参照テーブルのいずれかが相互にFK参照を持っている場合に、正しい順序でmustを実行することです。これらをメインのデプロイ後スクリプトに順番に含めます。これらのスクリプトを生成するツールを作成しておくと、依存関係の順序も解決されます。 「バージョン」の最後にこの生成ツールを実行して、静的参照データの現在の状態をキャプチャします。他のすべてのデータモーションスクリプトは基本的に特殊なケースになり、ほとんどの場合は使い捨てになります。その場合、次の2つのいずれかを実行できます。dbビルド/アプリバージョンに対してIFステートメントを使用するか、各スナップショットパッケージを作成した後に1回スクリプトを消去することができます。

SSDTはFKチェック制約を無効にし、展開後のスクリプトの実行後にのみ有効にすることを覚えておくと役立ちます。これにより、たとえば、新しい非nullフィールドにデータを入力する機会が得られます(ところで、この機能を有効にするには、非null列の一時的な「スマート」デフォルトを生成するオプションを有効にする必要があります)。ただし、FKチェック制約は、スキーマの変更のためにSSDTが再作成するテーブルに対してのみ無効になります。その他の場合は、チェック制約に関する苦情を回避するために、データモーションスクリプトが適切な順序で実行されるようにする必要があります(または、スクリプトで手動で無効化/再有効化する)。

DACPACは本質的にスナップショットであるため、DACPACが役立ちます。スキーマを記述する複数のXMLファイル(プロジェクトのビルド出力に似ています)が含まれますが、作成した時点で凍結されます。その後、SQLPACKAGE.EXEまたはデプロイプロバイダーを使用して、そのパッケージスナップショットを公開できます。 DACPACのバージョン管理の使用方法については、「登録済み」データアプリとの結び付きが強いため、まだよくわかりません。独自のバージョン管理スキームに固執していますが、DACPACのファイル名には独自のバージョン情報が含まれています。

より決定的で大胆な例を提供したいのですが、ここでも問題を解決しています。

SSDTについて本当に残念なことの1つは、DBProjとは異なり、現在は拡張可能でないことです。さまざまな点でDBProjよりもはるかに優れていますが、問題を回避するための事前/事後スクリプト内に何らかの方法が見つからない限り、デフォルトの動作をオーバーライドすることはできません。現時点で解決しようとしている問題の1つは、数千万のレコードがある場合、更新用テーブル(CCDR)を再作成するデフォルトの方法が本当に悪臭を放つことです。

-更新:この投稿はしばらく見ていませんが、最近アクティブになっているようですので、いくつかの重要なメモを追加すると思いました:VS2012を使用している場合、SSDTの2013年6月リリースにはデータがあります比較ツールが組み込まれており、拡張ポイントも提供されます。つまり、プロジェクトにBuild ContributorsとDeployment Plan Modifiersを含めることができるようになりました。

59
DevPrime

私はこのテーマについてこれ以上有用な情報を実際に見つけていませんが、ツールをいじくり回し、演奏するのに時間を費やしました。そして、私の質問に受け入れられる答えを思いついたと思います。これらは必ずしも最良の答えではありません。これらのシナリオをより適切にサポートするための他のメカニズムやベストプラクティスがあるかどうかはまだわかりませんが、私が思いついたのは次のとおりです。

データベースの特定のバージョンの展開前および展開後のスクリプトは、以前のバージョンからのデータの移行にのみ使用されます。すべての開発サイクルの開始時に、スクリプトは削除され、開発が進むにつれて、以前のバージョンから新しいバージョンに安全にデータを移行するために必要なSQLで肉付けされます。ここでの1つの例外は、データベース内の静的データです。このデータは設計時に既知であり、T-SQL MERGEステートメントの形式でポスト展開スクリプトに永続的に存在し続けます。これにより、最新バージョンのパブリッシュスクリプトのみを使用して、あらゆるバージョンのデータベースを新しい環境に展開できます。すべての開発サイクルの最後に、以前のバージョンから新しいバージョンへの発行スクリプトが生成されます。このスクリプトには、スキーマを移行するために生成されたSQLと、手作りのデプロイスクリプトが含まれます。はい、パブリッシュツールはデータベースに対して直接使用できることを知っていますが、これはクライアントにとっては良い選択肢ではありません。私はdacpacファイルも知っていますが、それらの使用方法はよくわかりません。生成された発行スクリプトは、実稼働環境のアップグレードで知っている最良のオプションのようです。

だから私のシナリオに答えるために:

1)データベースをv3からv8にアップグレードするには、v4、v5、v6などの生成された発行スクリプトを実行する必要があります。これは、現在の方法と非常によく似ています。それはよく理解されており、データベースプロジェクトは、これらのスクリプトの作成/保守をはるかに容易にするようです。

2)スキーマがデータの下から変更されると、展開前および展開後のスクリプトを使用して、新しいバージョンに必要な場所にデータを移行します。影響を受けるデータは、基本的に展開前スクリプトでバックアップされ、展開後スクリプトで元の場所に戻されます。

3)これらのシナリオや他のシナリオでこれらのツールを使用する最適な方法についてのアドバイスをまだ探しています。ここで何か問題があった場合、または他に注意すべき点がある場合はお知らせください!ありがとう!

9
Charles Josephs

SSDTを使用した私の経験では、データベースのバージョン番号(つまり、v1、v2 ... vXなど)の概念はややなくなります。これは、SSDTが宣言型データベース開発と呼ばれる開発パラダイムを提供するためです。これは、大まかに言って、SSDTにどの状態にしたいのかを伝え、SSDTが既に持っているものと比較してその状態にする責任を負わせることを意味します。このパラダイムでは、v4、次にv5などを展開するという概念はなくなります。

あなたが正しく述べているように、展開前および展開後のスクリプトは、データを管理する目的で存在します。

お役に立てば幸いです。

JT

4
jamiet

これまでのところ、このスレッドは優れていると言いたかっただけです。

私はまったく同じ懸念に取り組んでおり、かなり大きなレガシーアプリケーションで、組織のこの問題に取り組んでいます。 (TFSブランチ上で)SSDTへの移行プロセスを開始しましたが、展開プロセスを理解し、その過程でカスタム移行と参照/ルックアップデータを管理する必要があります。

さらに複雑なことに、アプリケーションは1つのコードベースですが、「顧客」ごとにカスタマイズできます。したがって、この1つのプロジェクトでは、おそらく通常の3つだけではなく、約190のデータベースを扱っています。私たちは常に展開を行っており、新しい顧客をかなり頻繁にセットアップしています。現在、旧式のインクリメンタルリリーススクリプト(およびそのバージョンで新しい顧客を作成するための関連スクリプト)を備えたPowerShellに大きく依存しています。これをすべて理解したら、貢献する予定ですが、他に学んだことを共有してください。最終的にはバージョンごとにカスタムリリーススクリプトを維持することになると思いますが、そうなるでしょう。プロジェクト内の各スクリプトを保守し、FromおよびTo SqlCmd変数を含めることについてのアイデアは非常に興味深いものです。それを行う場合、おそらく途中でプルーニングを行い、誰もがそのバージョンを過ぎたら、実際には古いアップグレードスクリプトを物理的に削除します。

ところで-サイドノート-無駄を最小限に抑えるというトピックについては、列の適切な命名/データ型の規則の実施を自動化する方法、およびすべての主キーと外部キーの自動生成命名規則、インデックスおよびチェック制約などについて。最も難しい部分は、ルールに従わない「派生物」を扱うことでした。誰かが興味を持っているなら、いつかそれを共有するかもしれませんが、今のところ、この展開、移行、および参照データのストーリーを大いに追求する必要があります。再度、感謝します。君たちが私の頭の中を正確に話し、今朝を探していたようだ。

3
Ryan White