Kobarin's Development Blog

C#やASP.NETなどについての記録です。

Azure SQL Database で、DBの照合順序の変更方法

Azureでは、SQL Databaseを新たに作成すると、照合順序がデフォルトとして「SQL_Latin1_General_CP1_CI_AS」になるため、
その後にTABLEにvarchar型などの文字列フィールドを作成すると、そのままだと全て「SQL_Latin1_General_CP1_CI_AS」になる(照合順序は、データベースと文字列フィールド別々に指定できる)。
例えば後から「Japanese_CI_AS」に変更する場合、フィールドに対して直接ALTERする事で対応するしかなくなる。
列の照合順序の設定または変更 - SQL Server | Microsoft Docs

ALTER TABLE dbo.MyTable 
ALTER COLUMN CharCol VARCHAR(50) COLLATE Japanese_CI_AI

フィールドの追加の度にこれでは流石に運用に難が生じるが、通常は「DBの照合順序は後から変更できない」とされる。
ただし、実は「データ層アプリケーションのインポート/エクスポート」を使う事で、”データベースの照合順序”の変更が可能である事がわかったので、ここから説明する。
情報源はこちら。
stackoverrun.com

方法を準に説明すると、以下の通り。ここではDB名は「MyDB」とする。

  1. SSMSでAzure のSQLに接続し、目的のDBを右クリックで「データ層アプリケーションのエクスポート」を実行(→MyDB.bacpac ファイルがダウンロードできる)
  2. MyDB.bacpacファイルのコピーを作成(例:MyDB.bacpac → MyDB2.bacpac)
  3. MyDB2.bacpac のファイル名を変更し、MyDB2.zip にする(実はbacpacとは、zipの拡張子を変えただけのファイル)
  4. 7-zip等を使ってzipを展開し、model.xml を開く(メモ帳でOK)
  5. 先頭の方に「Name="Collation" Value="SQL_Latin1_General_CP1_CI_AS"」となっている箇所があるので、Value部を「Japanese_CI_AS」に変更し、保存
  6. 次に、Origin.xml の Checksumの変更が必要なので、コマンドプロンプトで「CertUtil -hashfile "<model.xml の パス>" SHA256」を実行(参考: SQL AzureでエクスポートしたbacpacをローカルのSQLサーバーにインポートすると SQL72014が発生する - Qiita)し、得られたコードをOrigin.xml 内の「<Checksum Uri="/model.xml">ここに貼り付け</Checksum>」に貼り付ける。
  7. MyDB2内を再び圧縮し、MyDB2.zipが出来たら、MyDB2.bacpac にリネイム(注意:MyDB2を圧縮する際、7-zipでフォルダに対して圧縮すると、そのフォルダが余計に作成された形で圧縮されてしまい、後述するインポート時に「'Origin.xml' が dacpac パッケージにありません」とエラーが出てインポートできなくなるため、MyDB2フォルダ内のmodel.xmlを含む全ファイル&フォルダを選択して圧縮する)。
  8. SSMSに戻り、MyDBをいったん別のデータベース名に変更して退避させ(例:MyDB_backup)、「データベース」を右クリックし「データ層アプリケーションのインポート」を実行。
  9. 完了したら、MyDBのプロパティで照合順序が「Japanese_CI_AS」になっている事を確認して終了

Azureでwkhtmltopdfがサポートされた話

Webサイト上からHTML(URLで指定)をPDFに変換する処理にwkhtmltopdfを使う場合、従来Azureでは動作しなかったらしい。
調べてみると、以下の投稿が見つかった。
social.msdn.microsoft.com
ただし、

Azure now supports WKHTMLTOPDF. Please make sure you're using Basic, Standard, or Premium App Service Plan.

とあるように、Freeでは非対応らしい。
試したところ、たしかにFreeでは動作せずBasicでは出来た。

Visual Studio 2019からAzureにDeployできない問題

Visual Studio 2019からAzureにDeployする際、以下ののエラーとなる。

Web deployment task failed. (The type initializer for 'Microsoft.Web.Deployment.DeploymentManager' threw an exception.

状況をまとめると以下の通り。

  • ASP.NET Coreのプロジェクトをテンプレのまま何も編集していないため、コードや設定に問題があるわけではない
  • Buildは正常にできるものの、PublishでAzureにDeployする際に上記エラーとなる
  • Azureポータルで確認すると、インスタンスは出来ている(従って、https://XXXXXX.azurewebsites.net/ のサイトは存在するが、サイトは動作しない)

冒頭のエラーについて調べてみると、以下の投稿が見つかった。
stackoverflow.com
この中の以下のReplyが気になった。

I had the same problem but installing SQL 2012 and changing the registry didn't fix it. After reinstalling Web Deploy 3.5 on my development machine things got straightened out.

気になった理由は、ここ以外にも「Web Deploy」が問題になるという内容の情報が見つかったからだ。
そこで「プログラムの追加と削除」を確認してみると、以下の2つが見つかった。

  • Web Deploy 4.0
  • Web Deploy 2.0

古い2.0を削除し、再びVSのDeployを行った結果、無事に成功。う~ん、エラーメッセージもっと具体的に出してほしい。

【解決済み】SQL Server 2014の再インストール時「sql server データベース エンジンの復旧ハンドルの待機に失敗しました」エラー

概要

久々にSQLServerを動かそうとしたところ接続できず、管理ツールのサービス「SQL Server」も停止したまま起動できなかったため、SqlServer2014を再インストールしようとした。

症状

インストーラーからインストールを実行したところ、以下のエラーが発生した。

sql server データベース エンジンの復旧ハンドルの待機に失敗しました」

インストール結果としては、データベースエンジンだけがインストールに失敗している。

対策1:全て削除してから再インストール(解決できず)

「プログラムと機能」より「SQL」と名の付くアプリケーションを全て削除して再度インストールを試みたが改善せず。

対策2:「SQL Server データベースエンジン」のアカウント変更(解決!)

以下を参考に実行したところ、無事にインストール成功した。

www.sk-access.com

SQL Server 2016 SP1 Express」のインストールの途中で、「サーバーの構成」が表示されます。
サービスの
「SQL Server データベースエンジン」のアカウント名が
「NT Service\MSSQL$SQLEXPRESS」になっています。
この「SQL Server データベースエンジン」のアカウント名を
「NT AUTHORITY\NETWORK SERVICE」に変更します。

信頼レベル「Medium」(Medium-Trust)のサイトでは、ASP.NET MVCが実行できない可能性

私が個人的に契約しているWindowsホスティング会社に、MVCサイトを発行し実行したところ、セキュリティエラーが発生しました(System.Security.Policy.PolicyException)。
Visual Studioの開発環境で試してもエラーが出ないため、ホスティング会社に確認したところ「信頼レベルは”Medium”」だとの事なので、その辺りを疑ってみました。
VS上で同じ環境を作って試すため、web.config内に以下の行を付け加えてみました。

<system.web>
  <trust level="Medium" />
</system.web>

その結果、VSの開発環境でも同様のエラーが発生しました。



冒頭で発行したとするMVCのサイトは、VSで自動生成されたMVCサイトのままでほとんどに手を付けていない状態。
信頼レベルの制約で疑わしい点があるとするなら、

  1. OAuth
  2. 外部APIXML)へのアクセス
  3. SqlServerへのアクセス

程度ですが、2及び3については、既に発行済のASP.NET WebFormsで実行済みなので除外しました。
とすると、残るはOAuthのみ(他にあるかもしれないけど、それがダメならMedium-Trustって何も出来ないと同義ですよね)。


そこで、「こういう事例って他に結構あるのか?」と思い探してみると、こんな書込みが。
どうやら「ASP.NETの開発チームの公式見解としては、Medium-Trustは時代遅れ」という事です。
stackoverflow.com
理由としては、

  1. 「修正不可」とされていたMedium-Trustにまつわるバグを全て解決済み(デバッグではなく、Full-Trustにより解決したと思われる)
  2. ホスティング会社に対して、Medium-Trustから移行し、代わりにOSレベルの適切な分離をするようにガイダンスを提供済み
  3. これまで開発してきたフレームワークMVCやWebAPI等)からMedium-Trustのサポートを中止済み。今後これらのフレームワークにより作られたアプリケーションにはFull-Trustが求められる。

としている。つまりMedium-Trustは使うべきではないアクセス制限機能ということになります。
なお、ここでの「Medium-Trust」というのは「信頼レベル=Medium」というだけでなく、「Full」より下の「High」「Medium」「Low」「Minimum」の4つを全て含む総称としている点に注意です。


実際、このような書込みもあります。
stackoverflow.com
この中のリプライに

But, most of hosting provider offer full trust hosting now

とあるように、Full-Trustが米国(?)では一般的なようです。
ASP.NET MVCサイトのホスティング先をお探しの方は、あらかじめ運営会社に「信頼レベル」を確認していただく事をオススメします。

ASP.NET MVCでGoogleのOAuth 2.0 の認証をする

Visual StudioASP.NET MVCサイトのテンプレートには最初からOAuthの認証機能が付いているが、幾つか引っかかったのでメモしておきます。
基本的な流れは以下のサイトによくまとめられているため、割愛します(これ以上わかりやすく書けません)。
fnya.cocolog-nifty.com

ただ、上記の記事作成時点ではベータ版だったらしく、その後仕様が変わったのか、この通りに設定・操作を進めてもログインできません。
何故か、ログインページの「Google」ボタンを押しても、何も表示されないまま元のログインページに戻ってきてしまいます。

解決方法として見つかったのは、以下のスレッドです。
stackoverflow.com
これによると、Google Developer Consoleで「Google+ API」を有効にする必要があるようです。
Google Developer Consoleの左ペイン「APIとサービス」から「ライブラリ」を押し、「Google+ API」を有効にしてから再度実行するとOAuthログインできます。

Umbraco : 1つのデータベース内に複数サイト

Umbracoの開設は、下記サイトのようなチュートリアル通りに進めればほぼ難なく出来る事がわかりました。
www.buildinsider.net

ただ、複数サイトを作成しようとすると、幾つか問題があります。
Umbracoサイト毎にデータベースを用意するのであれば問題になりませんが、自社で使う簡易的なサイトや同じ顧客のためにサイトを複数作る時など、できれば同じデータベース内で管理したいと思います。
そうした場合、上記チュートリアルの通りに進めても上手くインストール出来ません。
Webサイト側はVisualStudiodで新たに作れば良いだけですが、データベース側(SQL server)ではTABLE(cmsContent等)が重複するため、インストール途中で失敗します。

そこで、以下の流れに沿って進める事で複数サイト開設ができたのでメモしておきます(例として2サイトを作成)。

  1. Umbracoサイトを2つ作成
  2. Umbraco用のデータベースを1つ作成
  3. SqlServerログインを2つ作成
  4. データベースロールを2つ作成
  5. 各DBロールに、スキーマレベルのCREATE TABLE権限を付与
  6. Umbracoインストー

設定例

なお、各サイトのログイン設定は以下の通りとします。

項目 サイト1 サイト2
データベース UmbracoDemoDb UmbracoDemoDb
ログイン umbuser1 umbuser2
スキーマ umb1 umb2
データベースロール umb_role1 umb_role2

それでは進めてみましょう。

手順

1.Umbracoサイトを2つ作成

Visual StudioでUmbracoのプロジェクトを2つ作成しましょう。この部分は説明の必要はないと思うので割愛します。

2.Umbraco用のデータベースを作成

SSMSでデータベースをUmbraco用に1つ作成します。ここでは「UmbracoDemoDb」というDBにします。

3.SqlServerログインを作成
  1. SqlServerManagementStudioを開く
  2. [セキュリティ]→[ログイン] で右クリックし、「新しいログイン」
  3. [ログイン名] に「umbuser1」を入力
  4. [SQL Server認証]を選択し、パスワードを登録
  5. [既定のデータベース]に「UmbracoDemoDb」を選択
  6. [ユーザーマッピング]で「UmbracoDemoDb」を選択し、[ユーザー]に「umbuser1」、[スキーマ]に「umb1」を入力

一般的な説明では「データベース ロール メンバーシップ」の「db_owner」にチェックを入れますが、ここはオフで。チェックを入れるとインストールに失敗します。

4.データベースロールを作成
  1. SSMSで [UmbracoDemoDb]→[セキュリティ]→[ロール]→[データベースロール] を右クリックし、「新しいデータベースロール作成」
  2. [ロール名]に「umb_role1」を入力
  3. [所有者]に「dbo」
  4. [このロールが所有するスキーマ]に「umb1」
  5. [このロールのメンバー]に「umbuser1」を選択
5.DBロールに、スキーマレベルのCREATE TABLE権限を付与

最後に、SSMSで以下のクエリーを実行します。

USE UmbracoDemoDb
GRANT ALTER ON Schema :: umb1 TO umb_role1
GRANT CREATE TABLE TO umb_role1
GO

このコードは以下の書込みを参考にしました。
serverfault.com
なお、実行すると以下のメッセージが表示されますが、正常に完了しているので大丈夫です。

sa、dbo、エンティティ所有者、information_schema、sys、または自分自身に対する権限を許可、拒否、または取り消すことはできません。

6.Umbracoインストー

以上で1サイト用のログインは完成です。
Umbracoのインストールで、ここで設定したログインを入力すれば、スキーマ付きでTABLEが登録されます。

2つ目以降のサイトも同様に、ログイン名・データベースロール名・スキーマ名を変えて設定し、Umbracoのインストール画面でログインすれば、指定したスキーマでTABLEが作成されます。
あと、Umbracoのよくある解説サイトでは、ログインを作成する際に「db_owner」を選択しますが、これをしてしまうとインストール時に失敗します(当方の場合は「umbracoMigrationが無効」と出ました)。
どうもアクセスできてしまうだけでエラーになってしまうので、ここではdb_ownerを外す事で指定スキーマにしかアクセス出来ないようにしています。