ツナ缶雑記

ぐうたらSEのブログです。主にマイクロソフト系技術を中心に扱います。

Core 第12世代の PC 構成を考える(マザーボードの選択)

f:id:masatsuna:20220126221204p:plain

Core 第 12 世代 CPU を用いた PC を作るシリーズの第 6 回は、マザーボードの選定について書いていこうと思います。 前回の記事はこちらからどうぞ。

tsuna-can.hateblo.jp

追加の条件を考える

マザーボード選定にあたって、追加で検討しておくべき条件を整理しておきます。

M.2 SSD スロット

システムドライブ用に 1 つ、仮想マシンのイメージ置き場に 1 つ、将来的な拡張のために 1 つ、全部で 3 本のスロットが欲しいと思っています。 システムドライブ用と仮想マシンのイメージ置き場用は必須で、拡張用のスロットはあればうれしい、という位置づけです。 いずれも確保できるなら PCIe 4.0 で接続したいですが、将来的な拡張スロットは PCIe 3.0 でも妥協できます。

最近はマザーボードに M.2 SSD のサーマルガードが付属しているものも増えています。 PCIe 4.0 で接続する場合、 M.2 SSD は相当発熱します。 サーマルガードなしで運用すると、サーマルスロットリングが発生するリスクが高まるため、できればマザーボード側にサーマルガードが付属していて欲しいです。 サーマルガードはなくても、別途用意すれば問題ないため、あればうれしい、のレベルです。

リア USB

リア側の USB は、何をどのくらい接続するのかによって、仕様を考えておくべきです。 私の場合、主に接続するのはマウスやキーボードなどの USB 機器と、 USB 接続のスピーカー、カメラの 4 つがあります。 いずれも USB 2.0 であれば問題なく動作します。 できる限り PC 直結で使いたいため、最低でも 4 つ USB ポートが必要です。 ただ、ギリギリの数だと拡張性が死んでしまうので、余裕をもって 6 ポートは欲しいところです。

リア側の USB Type-C 端子は今のところ不要です。 特に接続する機器を持っていません。 将来性を見るとあってもよさそうですが、現時点では特に使う予定がありません。

BIOS Flush

CPU やメモリを装着しなくても、 BIOS のアップデートを行うことのできる BIOS Flush 機能は必ずほしいです。 出始めたばかりの CPU やマザーボードは、 BIOS の作りこみが甘い部分も多く、アップデートしないと動ないことが割とよくあります。 メモリのオーバークロックをしたら動かなくなるのもあるあるです。 そういう時、 BIOS Flush ができるのは非常に助かります。

組み込み I/O ボード

前回作ったPC は組み込み I/O ボードがあるマザーボードを使いました。 これがあることで、リア側の見た目が大幅によくなります。 また組み立て時にボードの爪が端子の中に入ってしまうミスが発生しないというメリットもあります。

組み込み I/O ボードは、できればあったほうが嬉しいですが、今回は機能と価格を優先して選定しようと思います。

LAN

私のデスクトップ PC は、有線 LAN でしか接続しません。 有線 LAN は、将来性を考えて 2.5G LAN が欲しいと思っています。

WiFi は不要です。 Bluetooth 接続する機器もありません。

電源フェーズ数

気にしません。 過度なオーバークロックをするつもりは一切ないので、普通に動いてくれれば十分です。 Z690 が搭載されているマザーボードは、どれもある程度のオーバークロックを前提とした回路を持っています。 どのマザーボードヒートシンクがしっかりしていますし、激しい使い方をしない限り、発熱が問題にはなることはありません。 普通の使い方の範疇なら、フェーズ数とかはあまり気にする必要ないと個人的に思います。

必須条件をあげる

ここまでに検討してきた内容から、マザーボードの選択に影響を与える項目について再度まとめてみます。

項目 優先度 グレード、バージョン、数など
チップセット 決定 Z690
対応メモリ 決定 DDR4
フォームファクタ 決定 ATX
M.2 スロット 必須 PCIe 4.0 2 本以上(可能であれば 3 本、サーマルガードもあったらうれしい)
フロント USB Type-C 必須 可能であれば USB 3.2 Gen2x2 (1 ポート分)
フロント USB Type-A 必須 USB 3.2 Gen1 (2 ポート分)
リア USB Type-A 必須 4 ポート(可能であれば 6 ポート)以上、2.0 以上なら何でも OK
BIOS Flush 必須 できればバックパネルに欲しい
組み込み I/O ボード あったらうれしい、レベル
リア USB Type-C あったらうれしいがコスト次第
LAN 有線 2.5G (WiFi は不要)
電源フェーズ どうでもいい

この条件に合う Z690 マザーボードを探していきます。

マザーボードのグレード

Z690 のマザーボードだと、現時点で最安値はおよそ 26,000 円程度です。 高グレードになってくると、 70,000 円を超えるものもあったりします。 様々なところで言われていますが、高グレードのマザーボードを買ったところで、 PC の性能が上がる、なんてことはありません。 電源フェーズが増えたり、本格水冷に対応していたり、高クロックのメモリが使えたり。。。 普通に使う分にはほとんど関係ない機能差が、価格に反映されています。 そういったところを求めるユーザーには良いのでしょうが、一般的な使い方しかしない人には無駄な機能でしかありません。 私も一般的な使い方しかしないので、できる限り低コストで必要な機能の付いたものを選定しようと思います。

もちろん価格の近い物であれば、デザインとかの要素を絡めて決めていいと思います。 そもそも自作 PC は、自由に自分の好きなものを選べるのが良いところです。 悩みぬいて自分なりの価値基準で選定すれば幸せになれると思います。

DDR4 対応の Z690 マザーボード (ATX) を比較する

私は私の価値基準に従って、価格帯の低い物から、必要十分なものを探していこうと思います。 まずは今回比較検討するマザーボードを、価格帯と対応メモリ、フォームファクタで絞り込んでみます。

今回は ATX サイズ、 DDR4 対応の Z690 マザーボードのうち、 2022 年 1 月 25 日現在、最安値が 34,000 円を下回っているものを抽出しました。 これらを要件別に並べて、整理していきます。








M.2 SSD スロット

M.2 SSD のスロット数を PCIe のバージョン別に並べてみます。 かっこ外の数字はスロットの本数を、カッコ内の数字はスロットの中でマザーボードにサーマルガードがついているスロット数を表しています。

メーカー 製品 PCIe 4.0 PCIe 3.0
ASRock Z690 Pro RS 2 ( 1 ) 1 ( 0 )
GIGABYTE Z690 UD DDR4 (rev. 1.0) 3 ( 1 ) 0
MSI PRO Z690-A DDR4 3 ( 1 ) 1 ( 0 )
ASRock Z690 PG Riptide 2 ( 1 ) 1 ( 0 )
ASUS PRIME Z690-P D4 3 ( 1 ) 0
ASUS TUF GAMING Z690-PLUS D4 4 ( 3 ) 0
ASRock Z690 Steel Legend 2 ( 2 ) 1 ( 0 )

さすがにこの価格帯のものだと、サーマルガード付きの M.2 スロットは控えめになっています。 私の場合、 PCIe 4.0 のスロットが 2 本必須なので、どれを選んでも問題はなさそうです。 3 本目のストレージを PCIe 4.0 で接続するとなると選択肢は多少絞られますが、今回そこは必須にしていません。

並べてみると、 TUF GAMING Z690-PLUS D4 はこの中では特異な存在です。 同価格帯では M.2 SSD の機能が相当充実しています。

リア USB

次はリアパネル側の USB ポートを見ていきます。 まずは優先度の高い Type-A のポートから比較します。

メーカー 製品 2.0 3.2 Gen1 3.2 Gen2
ASRock Z690 Pro RS 2 2 2
GIGABYTE Z690 UD DDR4 (rev. 1.0) 4 4 1
MSI PRO Z690-A DDR4 4 2 1
ASRock Z690 PG Riptide 2 2 2
ASUS PRIME Z690-P D4 2 2 1
ASUS TUF GAMING Z690-PLUS D4 0 4 2
ASRock Z690 Steel Legend 0 4 1

ここは結構差があります。 必須要件の 4 ポートはどれもクリアしていますが、 6 ポートとなると脱落するものがいくつかあります。

続いて Type-C ポートも比較してみます。

メーカー 製品 3.2 Gen1 3.2 Gen2 3.2 Gen2x2
ASRock Z690 Pro RS 0 0 0
GIGABYTE Z690 UD DDR4 (rev. 1.0) 0 0 1
MSI PRO Z690-A DDR4 0 0 1
ASRock Z690 PG Riptide 0 0 1
ASUS PRIME Z690-P D4 0 0 1
ASUS TUF GAMING Z690-PLUS D4 1 0 1
ASRock Z690 Steel Legend 0 1 0

私の場合リア側の Type-C ポートは利用予定がないので、今のところどうでもいいかなーと思います。 TUF GAMING Z690-PLUS D4 は少し珍しくて、リア側に Type-C ポートが 2 つあります。

BIOS Flush / 組み込み I/O ボード

BIOS Flush と組み込み I/O ボードをまとめて比較してみます。 BIOS Flush の列は、ボタンがどこにあるかを示しています。 バックパネル上にあったほうが操作しやすいので評価は上です。

メーカー 製品 BIOS Flush 組み込み I/O ボード
ASRock Z690 Pro RS バックパネル上 ×
GIGABYTE Z690 UD DDR4 (rev. 1.0) マザーボード
MSI PRO Z690-A DDR4 バックパネル上 ×
ASRock Z690 PG Riptide バックパネル上 ×
ASUS PRIME Z690-P D4 - ×
ASUS TUF GAMING Z690-PLUS D4 -
ASRock Z690 Steel Legend バックパネル上

ここもかなり差がある部分でした。 ここまで比較的高評価だった TUF GAMING は、 必須と考えていた BIOS Flush がありません。

このクラスだと組み込み I/O ボードがないものもちらほらあります。 ここは優先度低い項目なので、機能面を優先して考えたいところです。

LAN

続いてネットワーク機能も比較してみます。

メーカー 製品 有線 LAN 無線 LAN
ASRock Z690 Pro RS Realtek 2.5G -
GIGABYTE Z690 UD DDR4 (rev. 1.0) Realtek 2.5G -
MSI PRO Z690-A DDR4 Intel 2.5G -
ASRock Z690 PG Riptide Killer 2.5G -
ASUS PRIME Z690-P D4 Realtek 2.5G -
ASUS TUF GAMING Z690-PLUS D4 Intel 2.5G -
ASRock Z690 Steel Legend Realtek 2.5G -

今回調べたマザーボードは、すべて 2.5G LAN に対応しており、大きな差はありません。 ただし、同じ 2.5G LAN でもメーカーには違いがあります。 メーカーを気にする方もいると思いますが、私はあまり気にしていません。 また無線 LAN も使わないので、搭載していなくて構いません。 今回比較する範囲では、機能差はほとんどないと言えそうです。

フロント USB

今回選定した PC ケースは、 MSI MPG SEKIRA 100P でした。


これには USB 3.2 Gen 1 Type-A のポートが 2 つ、 USB 3.2 Gen2x2 Type-C のポートが 1 つ付属しています。 これらを使いこなせるかどうかは重要なポイントです。

まずはフロント USB Type-A のピンヘッダを見てみます。

メーカー 製品 2.0 3.2 Gen1 3.2 Gen2
ASRock Z690 Pro RS 2 2 0
GIGABYTE Z690 UD DDR4 (rev. 1.0) 2 1 0
MSI PRO Z690-A DDR4 2 2 0
ASRock Z690 PG Riptide 2 2 0
ASUS PRIME Z690-P D4 2 2 0
ASUS TUF GAMING Z690-PLUS D4 2 1 0
ASRock Z690 Steel Legend 2 2 0

USB Type-A の場合、マザーボード上にピンヘッダが 1 つあれば、ケース側で 2 ポート分の USB Type-A 端子を利用できます。 ですので、USB 3.2 Gen 1 Type-A のピンヘッダーが 1 つあれば十分です。 この要件はどのマザーボードもクリアしています。

続いて USB Type-C のポートも見ていきます。

メーカー 製品 3.2 Gen1 3.2 Gen2 3.2 Gen2x2
ASRock Z690 Pro RS 0 0 1
GIGABYTE Z690 UD DDR4 (rev. 1.0) 1 0 0
MSI PRO Z690-A DDR4 0 1 0
ASRock Z690 PG Riptide 1 0 0
ASUS PRIME Z690-P D4 1 0 0
ASUS TUF GAMING Z690-PLUS D4 0 1 0
ASRock Z690 Steel Legend 0 0 1

USB Type-C は、マザーボード上 1 ポートでフロント 1 ポート分の端子を利用できます。 今回の PC ケースはは USB 3.2 Gen2x2 対応のポートが 1 つあります。 ぜひとも USB 3.2 Gen2x2 を使いたいところです。

どのマザーボードも USB Type-C 用のピンヘッダは装備しています。 しかし、採用しているバージョンは結構差があります。 USB 3.2 Gen2x2 を使おうとすると、 ASRock の Z690 Pro RS または Z690 Steel Legend しか選択できません。

評価項目を並べる

ここまで確認してきた内容をまとめて、評価項目ごとに要件との合致具合を確認してみます。 私の用途で差異がなかった部分は表から除外しています。

メーカー 製品 M.2 SSD リア USB(A) フロント USB Gen2x2(C) BIOS Flush 組み込み I/O ボード
ASRock Z690 Pro RS 6 ×
GIGABYTE Z690 UD DDR4 (rev. 1.0) 9 ×
MSI PRO Z690-A DDR4 7 ×
ASRock Z690 PG Riptide 6 × ×
ASUS PRIME Z690-P D4 5 × × ×
ASUS TUF GAMING Z690-PLUS D4 6 ×
ASRock Z690 Steel Legend 5

こう眺めてみると、機能面での私の要求に最もあっているのは ASRock の Z690 Pro RS でした。 MSI の PRO Z690-A DDR4 も同等の機能を持っていますが、今回重視しているフロント USB 3.2 Gen2x2 の機能差によって、 Z690 Pro RS を選ぶことにしました。 M.2 SSD は PRO Z690-A DDR4 のほうが機能豊富で要件にあうのですが、今回はフロント USB Type-C のほうを優先しようと思います。

また Z690 Steel Legend もいいところをついています。 リア側の USB ポートが希望数に対して 1 つ足りないものの、最低限の数はクリアしています。 またほかの条件はすべてクリアしています。 ここは正直価格差で考えました。 機能面での差異は組み込み I/O ボードのほかに、リア USB のバージョン差異とポート数の差異があります。 Z690 Pro RS は 26,050 円、 Z690 Steel Legend は 33,800 円です*1。 この価格差と機能差/装備差が適切なのか考えた結果、コストとリア USB のポート数を優先することにしました。 7,000 円差は大きいです。

Z690 Pro RS は PCIe 4.0 の M.2 SSD が 2 本あり、そのうちサーマルガードがついているものが 1 つしかありません。 この辺は SSD 選定の時に注意が必要そうです。 組み込み I/O ボードがないのは残念ですが、現時点では必要十分な構成が組めそうです。


まとめ

今回はマザーボードの選定について考えてきました。 すでに選定している PC ケース MSI MPG SEKIRA 100P との組み合わせや、私の用途を総合して考えたところ、 ASRock の Z690 Pro RS を採用することが決まりました。

次回は CPU クーラーの選定について書こうと思います。

*1:いずれも 2022 年 1 月 25 日現在、価格.com の最安値で比較。

Core 第12世代の PC 構成を考える(Z690 / H670 / B660 / H610 の選択)

f:id:masatsuna:20220121004811p:plain

Core 第 12 世代 CPU を用いた PC を作るシリーズの第 5 回は、マザーボードの選定について書いていこうと思います。 前回の記事はこちらからどうぞ。

tsuna-can.hateblo.jp

おさらい

ここまでに決めてきた構成を再度おさらいしておきます。

パーツ 選定品
CPU
Intel Core i7 12700K
PC ケース
MSI MPG SEKIRA 100P

これらのパーツを生かすマザーボードを選択していきます。

Z690 / H670 / B660 / H610 の選択

マザーボードを決めるにあたって、まずはチップセットを選定しなければなりません。 Core 第12世代 CPU で利用できるチップセットは 4 種類あります。 まずはこれらのチップセットで、普通に PC を使う人が着目すべき部分をピックアップして見てみましょう。

Z690 H670 B660 H610
CPU オーバークロック × × ×
メモリオーバークロック ×
PCIe 5.0 レーン数(CPU) 16 16 16 16
PCIe 4.0 レーン数(CPU) 4 4 4 0
PCIe 4.0 レーン数(チップセット) 12 12 6 0
PCIe 3.0 レーン数(チップセット) 16 12 8 8
USB 3.2 Gen2x2 4 2 2 0
USB 3.2 Gen2x1 10 4 4 2
USB 3.2 Gen1 10 8 6 4

まず目につくのはオーバークロックの部分です。 今回選定している K 付きの CPU は、オーバークロックが可能なモデルです。 K 付きや KF 付き CPU でオーバークロックをしたいのであれば、 Z690 チップセット 1 択です。 メモリのオーバークロックは B660 より上位のチップセットなら対応しています。

続いてPCIe について見てみます。 通常グラフィックボードを接続する CPU 直結の PCIe 5.0 16 レーンは、どのチップセットも確保されています。 NVMe で接続する M.2 SSD 向けの PCIe レーンは、チップセットごとに少々差があります。 CPU 直結の PCIe 4.0 は、 B660 より上のモデルなら 4 レーンあります。 通常これを M.2 SSD の接続のために使用します。

チップセット側の PCIe 4.0 も差異があります。 M.2 SSD を 2 つ以上接続したいのであれば、チップセット側の PCIe レーンも使用して M.2 SSD を接続することになります。 2 つとも PCIe 4.0 で接続したいなら、チップセット側にも PCIe 4.0 を 4 レーン確保する必要があるため、 B660 より上位の物を選ばなければなりません。

USB ポート数も結構差があります。 上位のチップセットほど、多くの USB ポートを備えることができる仕様になっています。

H610 は選択肢から除外

比較表を見てもわかる通り、 H610 チップセットは今回の構成に対して貧弱すぎます。 私の場合これを選ぶ理由はないので、今回は検討テーブルから除外します。

PCIe 4.0 のレーン数

今回私は PCIe 4.0 対応の M.2 SSD を 2 本搭載しようとしています。 1 つはシステムドライブ用、もう 1 つは仮想マシンのイメージ置き場です。

B660 でもこの構成なら確保できます。 しかし、拡張性という意味では相当物足りなくなります。 私が将来やりそうな拡張は、M.2 SSD の追加です。 現在 SATA 接続の 2.5 インチ SSD を 2 本所有しています。 これを M.2 SSD 1 つに統合して置き換える可能性を否定できません。 そうなると、 PCIe 4.0 で 3 本目の M.2 SSD を差し込む余裕が欲しくなります。

この時点で B660 は除外せざるを得ません。

Z690 vs H670

最終的に残ったのは Z690 と H670 です。 最初に述べた通り CPU のオーバークロックに対応しているかどうかが、これらの最も大きな差です。

また製品数という意味でも、大きな差があります。 Z690 は数多くの製品が登場していますが、 H670 チップセットを載せている製品は、少数しかありません。 今後 H670 を搭載するマザーボードがリリースされる予定も見聞きします。 しかし、それでも製品バリエーションは Z690 の圧勝だと思います。

チップセット自体の差異も当然ありますが、マザーボードにそれらをフルスペックで搭載することはほぼありません。 Z690 は、低価格帯から高価格帯まで幅広く様々な仕様のものがあります。 そのため、自分の必要なものだけを装備したマザーボードを選択することができる可能性が高くなります。 しかし H670 は低価格帯のマザーボードしかありません。 チップセットはサポートしていても、コストカットのため搭載していない機能があったりします。 製品バリエーションが少ないと、自分の要求に完全に合致する 1 枚を見つけることが困難になるのです。

Z690 を選択

今回は Z690 チップセットを選択しようと思います。 PCIe レーン数や USB ポート数については、私の用途では H670 でも十分だと思います。 しかし、 CPU に Core i7 12700K を選択したこともあり、オーバークロックできた方がいろいろ楽しめそうなんじゃないかと思いました。 また、選択肢の多さも魅力に感じました。 そんなこんなで、今回は Z690 チップセットマザーボードから選ぶことにします。

まとめ

今回はチップセットの選定まで、どのように考えたかを書き記してみました。 次回はさらに踏み込んで、具体的なマザーボードの選定について書いてみようと思います。

Core 第12世代の PC 構成を考える(PCケース編 その2)

f:id:masatsuna:20220118011254p:plain

Core 第 12 世代 CPU を用いた PC を作るシリーズの第 4 回は、前回の続きで、 PC ケースの選定について書いていきます。 前回の記事はこちらからどうぞ。

tsuna-can.hateblo.jp

PC ケースの使い勝手からさらに絞り込む

私のデスクは、 PC をデスク下の PC 置き場に配置しています。 実際に使っているものとはちょっと違うのですが、こういった箱型の置き場に PC を置いています。


DEWEL CPUワゴン パソコンワゴン 60x50x30cm PCワゴン キャスター付き デスクサイド収納 デスク下ワゴン 棚板高さ3段調節 排熱を妨げない 丸角加工 メラミン加工

こういったものの中に配置する場合、端子類や電源スイッチが PC ケースの上部に、しかもできる限り前面パネルの上にあったほうが、使い勝手が良くなります。 PC は箱の中から動かすことはないので、天面の奥の方に端子があると使えません。 またケース前面パネル側に端子があるタイプの物も、下の方に手を伸ばさなければならないので使いにくいです。 特に端子が PC ケース下部にあるものは私の PC 設置方法にあいません。

PC の設置方法、設置場所から考える

ちょっと本題からそれてしまいますが、 PC ケースの選定にあたってどこに USB ポートがあるとうれしいか考察してみます。 あくまで私の考えなので、ご参考までに。

デスク下配置、天面に余裕なし

私のように、デスク下に PC を配置し、箱型の置き場に配置している場合、 PC 天面に手を差し込む隙間がないと思います。 そういった場合は、 PC ケース前面の上部に端子があるものや、天面の前面パネル側に端子があるものを選ぶと使い勝手が良いです。 また配置できるのであれば、それなりに高さのある PC ケースを選んでおいた方が、座ったまま楽に端子類にアクセスできます。

例えば PC ケース前面の上部に端子があるものだとThermaltake の Versa H26 は非常に人気があります。


前回紹介した Flactal Design の Define 7 Compact も、この要件を満たしてくれるケースです。 このケースは天面の前面パネル側に端子があります。 またこのケースは天面とデスクの間に隙間がない場合も、少しだけ PC ケースを前面にオフセット配置できるように工夫されています。 デスクから前面パネルの頭を少しはみ出させて配置することを想定した位置に足があるので、 PC ケース天面とデスクの間に隙間がなくても使いやすい位置に端子を持ってこれます。

デスク下配置、天面に余裕あり

この場合は PC ケース上部、そしてできる限り前面パネル寄りに端子のあるものを選ぶと良いです。 いくら天面に余裕があるとしても、デスク下に配置する以上、奥側にある端子は使いにくいです。

例えば MSICreator 400M は、天面に余裕がない場合選択肢から除外されがちですが、余裕があれば使えるケースになります。 このケースは、先ほど紹介した Flactal Design の Define 7 Compact より若干端子が奥側に寄っているので、天面に余裕がないと端子に干渉することがあります。


座席横配置、床置き

PC をデスク下ではなく、椅子の横に床置きする場合、端子が天面にあれば使い勝手は十分です。 天面方向にはなるべく障害物を置かない方が、より端子類の使い勝手は良くなると思います。

例えば、デスク下配置ではあまり選択肢にあげることができない、天面の左右サイドに端子が寄っているような PC ケースも選択しやすくなります。 MSI の MPG QUIETUDE 100S は、天面右側に端子が寄っています。 椅子の左側に置くのなら最適なケースになりそうです。


卓上配置

卓上に配置する場合は、 PC ケース前面パネルか側面パネルに端子類があったほうが使いやすいです。 また卓上配置するならコンパクトなものの方が良いと思います。 PC を縦向きに置くなら前面パネル、横向きに置くなら側面パネルに端子があるのがベストでしょう。 目線よりさらに高い位置に PC を配置するなら、 PC ケース底面近くに端子があるものを選びましょう。

2020 ~ 2021 年くらいに結構話題になっていたケースに COOLER MASTER の MASTERBOX Q500L があります。 これは側面に端子があるのですが、端子の位置を自由に組み替えできます。 様々な配置に対応するケースと言えます。


また LIAN LI の O11 Dynamic も卓上配置に適していると思います。 いわゆる「映える」 PC ケースで、前面パネルもガラスになっているタイプです。 卓上配置して、さらにピカピカさせたい場合はこういう製品を選ぶのもありだと思います。 端子は前面パネルにあります。


結局どれを選択するか

途中様々な考察を挟みましたが、私の場合はデスク下配置で、天面にも余裕がありません。 よって端子類ができる限り前面パネルに寄っているものから選ぶことにしました。 N WIN の 301C IW-CF07 はケース前面に端子があるので私の環境では除外せざるを得ません。 結局残ったのは Flactal Design Define 7 Compact / Meshify 2 Compact と、今回初めて見た MSI MPG SEKIRA 100P でした。

Fractal Design の PC ケースが優秀なことは、過去触ってきてよく知っています。 しかし、 USB 3.2 Gen 2x2 の将来性を見たとき、 MSI のケースを選択するのも悪くないと考えました。 また USB ポートもそれほど数が必要ないので、今回は思い切って MSI MPG SEKIRA 100P を選択することにしました。


まとめ

PC ケースは、 USB 端子の種類などの機能面や、見た目などの装飾面、特にスペックとして語られることのない静音性・排熱性・組み立てやすさ・建付けの良さなど、様々な観点を総合的に判断して選ぶものだと思います。 機能面を犠牲にして、装飾に全振りするような考え方もありです。 それだけ選択肢が多く、選ぶのが楽しいパーツであるとも言えます。

私の場合、機能面を重視して PC ケースを選ぶことがほとんどです。 また端子の位置など、毎日の使い勝手が良くなる PC ケースを選ぶようにしています。 見た目は優先順位が落ちるので、どうしても毎度同じようなケースばかり選定してしまっていました。

MSI MPG SEKIRA 100P は、側面がガラスパネルの割に、全体的に落ち着いた見た目をしていると思います*1。 側面パネルがガラスの物を選ぶのはこれが初めてです。 機能面も十分で、私の要件にはよく合致する製品だと思いました。

次回はいよいよマザーボードの選定を行います。

*1:ドラゴンロゴはいらないけど

Core 第12世代の PC 構成を考える(PCケース編 その1)

f:id:masatsuna:20220116233048p:plain

Core 第 12 世代 CPU を用いた PC を作るシリーズの第 3 回は、マザーボード選定にあたって必要な PC ケースの選択について考えてみます。 前回の記事はこちらからどうぞ。

tsuna-can.hateblo.jp

なぜ PC ケースを先に決めるのか

PC ケースには様々な大きさのものがあります。 また USB のポートや電源サイズなど、パーツ選定の制約になってしまうような要素もいくつか存在します。 小さなケースほど制約が強く、選べるパーツの範囲が狭まります。 作業スペースも小さくなるため、組み立てがめんどくさくなります。

またPC ケースは PC の見た目を決定づける超重要なパーツであると個人的に思います。 自分の趣味を炸裂させるべきパーツです。 それと同時に、 PC の使い勝手にも関わるパーツです。 PC の置き場所や、使用する周辺機器など、状況や優先度によって選ぶべきケースは変わってきます。

今回は私のデスクまわりの環境を例にして、どのような手順でケースを選定していったか書いてみようと思います。 ちなみに私はあまり見た目にこだわりなく、使い勝手を重視しています。 ピカピカ光らせる趣味もありません。

大まかなサイズを決める

今回は Core i7 12700K を使うことにしました。 Core i7 12700K はそこそこ熱を発生させる CPU です。 あまりにも小さなケースでは、熱がこもってうまく CPU を冷却できない可能性があります。 そのため、ミドルタワークラスの PC ケースから選定することにしました。

私のデスク環境では、 PC を配置できる場所の大きさに制限があります。 デスク下に PC を配置するためのスペースがあり、奥行 520mm 、幅 240mm 、高さ 480mm が限界サイズです。 限界サイズのケースを配置すると、上面からの吸気はほぼ見込めず、前面から背面方向へのエアフローしか確保できない状態になります。

現状そのスペースには Fractal Design の Define 7 を置いています。 しかし、このケースは奥行きが 547mm もあるため、ケース前面がデスク手前に 5cm くらいはみ出てしまっています。 また限界まで奥に配置しているため、背面のスペースもかなり狭くなっています。


Define 7 は静音性に優れる非常に優秀なケースだと思うのですが、本音ではもう少し小さいサイズしたいと思っていました。 ただ、幅の小さいケースを選定してしまうと、 CPU クーラーの選択肢が広がりません。 幅は限界サイズまであっても邪魔にならないので、収納場所に収まる範囲で幅広なものを選ぼうと思います。

DVD ドライブの有無

これまで私は DVD ドライブを内蔵できるケースをなんとなく選択してきました。 自分の感覚では結構頻繁に使っていて、まだまだ使うケースが多いと思い込んでつけていたのです。 ところが、近年発売されている PC ケースの多くは、 DVD ドライブを内蔵できません。 内蔵できるとしても、 Define 7 のような大きなサイズのものがほとんどです。 本当に DVD ドライブを使う機会が多いのか、昨年 1 年間自分を観察してみました。 そうすると、年に数回程度しか使っていないことがわかりました。 そのような利用頻度であれば、 DVD ドライブを内蔵する必要はなさそうです。 手元に外付け DVD ドライブを置いておけば十分代替できます。 そんなこんなで、初めて DVD ドライブ非搭載の PC ケースを選択肢に加えて、排熱と省スペース性の両立できそうなものから選ぶこととしました。

USB ポートの種類と数

PC ケースには通常 USB ポートやイヤホンジャックなど、マザーボードと接続することで使えるようになるポートがついています。 今回は仕様に差が出やすい USB ポートの種類と数に着目して選定してみます。

現状 USB は、転送速度やコネクターの形状などによって、様々な種類があります。 現在 PC ケースによく利用されているものに限って、ざっくり整理してみるとこんな感じです。

USB 2.0 USB 3.2 Gen 1 USB 3.2 Gen 2 USB 3.2 Gen 2x2
転送速度 480Mbps 5Gbps 10Gbps 20Gbps
別名(旧称) USB 3.0、USB 3.1 Gen 1 USB 3.1 Gen 2
PC ケースの主なコネクター形状 Type-A Type-A / Type-C Type-A / Type-C Type-C のみ

現時点で最も転送速度が速いのは USB 3.2 Gen 2x2 です。 このコネクターを利用するかどうかで、選定する PC ケースの幅は相当変わってきてしまいます。

私の用途の範囲で、 USB 3.2 Gen 2x2 のコネクターを使いたいと思うケースは、高速な外付けハードディスクを使う場合に限られます。 そして現時点でそのような機器を保持していないので、今すぐ必要とは言えません。 将来性をどこまで見越すのかや、いつまで同じ PC ケースを使いまわすのかによって、検討したほうがよさそうです。

私の場合、 PC ケースを変えず、中身だけ取り換えるような使い方を過去良くしてきました。 その方が低コストで PC をスペックアップできます。 見た目に対するこだわりがそれほどない私にとって、 PC ケースは使いまわすパーツの筆頭です。 そうなると、同じ PC ケースを長期間使い続けることになります*1。 そういう使い方をするのであれば、 PC ケース側の仕様をできる限り最新化しておく方が、長く使い続けるのに役立ちます。

USB ポートの数は接続したい機器の数にあわせて考えるべきです。 私の場合、 PC ケースの USB ポートを使うのは、外付けの DVD ドライブやハードディスク、ゲームパットくらいです。 前述のとおり、 Type-C ポートを使うのは外付けハードディスクくらいで、他はほとんど転送速度を気にするような機器を接続しません。 またマウスやキーボードなどの機器は、マザーボードのリアパネルに付属するポートを使うため、 PC ケース側のポート数はそれほど必要ありません。 現時点でも、同時に 2 つ以上の機器を接続して使うケースはほとんどありません。

自分自身の使い方や、将来性をふまえて、私は USB 3.1 Gen 2x2 の Type-C ポートが 1 つ、 USB 3.2 Gen 1 または Gen 2 の Type-A ポートが 2 つあるものから選定することにしました。 できれば USB 2.0 のポートが別にあればうれしいですが、そもそも接続する機器の数が少ないので必須ではない、という位置づけにしています。

スマホをつなぎたいとか、人によって USB ポートの使い方は様々だと思いますので、同時に使う数がどのくらいあるかで判断するのが良いと思います。

3.5 インチ HDD や 2.5 インチ SSD の有無

最近の PC は、 3.5 インチ HDD や 2.5 インチ SSD を接続する必要性がだいぶ薄くなってきています。 動画などの大容量ファイルを大量に保存するのでなければ、 M.2 SSD だけを使って、現実的なコストで PC を組み立てることができてしまいます。 私もローカルに大量のファイルを置くことはありません。 唯一の大容量ファイルは、仮想マシンのイメージだけです。 それも最大 500GB 程度なので記憶装置の数は控えめで問題ありません。

しかし、手元に過去のマシンから移植し続けている 2.5 インチ SSD が 2 つ( 1TB / 500GB )あります。 これをいきなり廃棄するのは勇気の必要な決断です。 また 3.5 インチ HDD もあるにはあるのですが、現時点では使っておらず、今後も利用する可能性は限りなく低いと思われます。 よって HDD や 2.5 インチ SSD の配置場所は、 2 つあれば十分です。 どちらの SSD も古くなってきているため、 2TB クラスの SSD に換装して 1 台に集約することも視野に入れています。

PC ケースを絞り込む

これらの条件にあうような PC ケースを探してみると、めちゃくちゃ数が少ないことがわかります。 そもそも USB 3.2 Gen 2x2 をサポートしている PC ケースが圧倒的に少ないのです。 価格.comGoogle 検索を駆使して、手広く探してみました。 また数があまりにも少ないので、 USB Type-C を Gen 2x2 ではなく Gen 2 まで広げたうえで、価格控えめなものに絞って探してみると、以下のようなものが見つかりました。





まとめ

今回はどういった観点で PC ケースを選べばよいか、また選ぶ手順をまとめてみました。 次回はこれらの PC ケースから、さらに絞り込んでいくためにどんなことを考えたか、私の経験を解説しようと思います。

*1:ちなみに以前使っていた PC ケースは、 15 年くらい使っていました。ほとんどの USB ポートが劣化して使えなくなり、電源ボタンも反応が悪くなり、いい加減捨てよう、となった記憶があります。

Core 第12世代の PC 構成を考える(DDR4 vs DDR5)

f:id:masatsuna:20220112010252p:plain

Core 第 12 世代 CPU を用いた PC を作るシリーズの第 2 回は、マザーボード選定にあたって必要なメモリの規格について考えてみます。 前回の記事はこちらからどうぞ。

tsuna-can.hateblo.jp

DDR4 vs DDR5

Core 第 12 世代となって、ついに DDR5 という高速なメモリ規格がサポートされるようになりました。 Core 第 12 世代 CPU は DDR4 と DDR5 、どちらにも対応していますが、これらは互換性がありません。 マザーボードは DDR4 と DDR5 、どちらか一方のみをサポートするので、マザーボード選定にあたってまずメモリの規格を選定しなければなりません。

私は DDR4 を選定することにしました。 理由とか考察を書いていきます。

速度差はあるのか

各種メディアで DDR4 と DDR5 の違いがレポートされています。 それらの記事を参照すると、現時点で DDR4 と DDR5 で、各種ベンチマークのスコアに大きな差はない、ということがわかっています。 DDR5 はリリース間もない製品です。 そのため、全般的に見てクロックが抑え気味になっているように思います。 またメモリコントローラーの動作も Gear2 または Gear4 となるため、速度の足を引っ張っているようです。

それに対して DDR4 は、すでにリリースから 7 年ほど経過しており、動作速度も大きく上がってきています。 将来的に見れば DDR5 へと置き換わっていくでしょうが、現時点ではそれほど大きな性能差があるとは言えません。

このような現象は、 DDR3 から DDR4 への過渡期でも起きていました。 最初に DDR4 をサポートした Core シリーズは第 6 世代でした。 例えば Core i7 6700K だと、メモリのサポート状況は以下のようになっています。

DDR4-1866/2133, DDR3L-1333/1600 @ 1.35V

今だと DDR4 3200 が普通になりましたし、 OC メモリだと 5000 オーバーで動くものもあったりします。 今では考えられないくらい DDR4 メモリの動作クロックは抑えられた状態で登場していたのです。

これを今の DDR5 に置き換えて考えてみると、現在販売されている DDR5 メモリは、そんなにツヨツヨではないことが想像できます。 DDR5 の真の力は引き出されていないと思うのです。

将来性を買う必要があるか

メモリの高速化は、 PC の動作速度の向上に一定程度役立ちますが、速度差を体感できるかは微妙なところです。 また前述のとおり、現時点で真の力が引き出されていない DDR5 メモリを、今すぐ使うことに価値があるか、考えてみてもよさそうです。 DDR5 メモリの動作速度は将来的に上がるでしょうが、ツヨツヨとは言えないメモリを今慌てて導入する必要性は薄いように思います。

入手性

世界的な半導体不足のあおりを受ける形で、 DDR5 メモリも市中在庫が相当に少ない状況が続いています。 メーカーや細かな仕様にこだわらなければ、専門店でたまに購入できるような状況にはなってきましたが、お世辞にも在庫豊富とは言えません。 マザーボードとの抱き合わせ販売をしている店舗も多くあるようです。

価格

価格差も相当あると言えます。 DDR5 メモリ( 16GB × 2 枚)の場合、安くても 4 万円中盤くらいの価格設定がされています。 5 万円を超えるのも当たり前、という状況です。


それに対して DDR4 メモリは、同じく 16GB × 2 枚の構成で、 1 万円前半です。 自作 PC にコスパを求めるのはあまり良くないと思いますが、私にとってこの差はあまりにも大きすぎます。


まとめ

総合的に判断すると、現時点で DDR5 メモリを購入する意味はほとんどないと考えます。 入手性が悪く、価格が高いわりに、それほど性能があがるわけでもありません。 今のところは「ロマン枠」を出ないと言っても良いと思います。

というわけで、今回はマザーボードの選定にあたって必要なメモリの選定を行いました。 次回は PC ケースの選定を行い、マザーボード選定の基礎データを固めていこうと思います。

Core 第12世代の PC 構成を考える(CPU編)

f:id:masatsuna:20220110224449p:plain

ついに待ちに待った Intel Core シリーズの第 12 世代 CPU が発売されました。 年明け後マークなしの SKU も発表され、各種ベンチマークも明らかになり、構成を選択しやすい状況になったように思います。 というわけで今回から数回に分けて、 Core 12 世代の CPU を使った PC の構成について考えてみようと思います。

対象ユーザー

私自身です。 PC の主な用途はアプリケーション開発用です。 Hyper-V や Docker Desktop を用いた仮想環境を手元で稼働させながら、アプリケーションの開発を行います。 仮想マシンは複数台立ち上げることもあります。

現状ゲームはやりたいけど時間が取れなくてできていません。 今後はやりたいなーと思っています。

どの SKU を選択するか

Core 第 12 世代も、多くの SKU がリリースされています。 まずは Core i3 ~ i9 の中でどれを選択するか、といったあたりを考察していきます*1

可能な限りコア数を重視する

※本稿では、論理コアの数(=スレッド数)のことをコア数と表現しています。

以前アプリケーション開発にはどの程度のコア数が必要なのか、簡単に検証してみたことがあります。

tsuna-can.hateblo.jp

ストレスなくアプリケーションの開発を進めたいなら最低でも 8 コアあったほうが良いことがわかっています。 規模の大きなアプリケーションを開発するなら、 12 コアある方がより良い、という結果でした。 またシングルスレッドの性能はある程度必要であるものの、コンパイル速度向上にはコア数のほうが重要であるという傾向も出ていました。

tsuna-can.hateblo.jp

私の用途では仮想環境を使うことから、それらにある程度コアを割り当ててあげないと、全体的に動作がもっさりします。 総合的に見ると、最低でも 16 コア以上の CPU を選択したほうが幸せになれそうであることは明らかです。 この条件を満たす Core 第 12 世代 CPU は以下の通りです。

  • Core i9 12900K / 12900KF / 12900 / 12900F / 12900T (P Core × 8、E Core × 8、24 論理コア)
  • Core i7 12700K / 12700KF / 12700 / 12700F / 12700T (P Core × 8、E Core × 4、20 論理コア)
  • Core i5 12600K / 12600KF (P Core × 6、E Core × 4、16 論理コア)

この中から選択することになりそうです。

T シリーズは除外する

コア数だけで見ると、 12900T や 12700T も選択肢に入ってきます。 T シリーズは省電力向けの SKU で、小型 PC を組みたい人向けの SKU と位置付けられています。 省電力な分、同じ型番であっても性能が大きく下げられているのが特徴です。

アプリケーション開発を行う場合、 CPU は一時的に高速に回ってもらわなければなりません。 また常時起動するような PC でもないので、省電力性をそこまで求めているわけでもありません。 そう考えると、 T シリーズは私の用途に合っているとは言えません。

P コアの数に注目する

Core 第 12 世代 CPU は、高速処理を実現する P Core と、高効率な処理を実現する E Core が組み合わされています。 アプリケーション開発で最もパワーを要するコンパイル作業は、主に P コアを利用していくことが想定されます。 よって P Core の多い CPU のほうが用途に合っています。 以前の検証結果から、仮想マシンを使わないのであれば Core i5 12600K / 12600KF あたりでも十分ですが、私の用途には少しコア不足を感じます。 ということで、 Core i5 のラインナップも今回は除外します。



内臓 GPU の要否

ゲームやるのであれば、グラフィックボードを別に用意することが当たり前になっています。 そうしないと新しめのゲームはほとんどまともにプレイできない状況です。 しかし、ゲームをプレイしない場合や、本当に軽いブラウザゲームしかやらない、というような人は、グラフィックボードを買う必要ないと思います。 いま必要のないものを最初からそろえる必要がないのも、 PC を自作する価値のひとつだと思います。 特に最近はグラフィックボードの価格が高騰しまくっているので、慌てて購入しても、相当高い値段で買うことになってしまいます。

例えば私の購入した RTX 3070 は、2021/1/10 現在の値段が約 11 万円です。 1 年前に私が購入した値段は 7 万円を切っていました。 今すぐほしい人は買えばいいと思いますが(ほしい時が買い時なので)、古いものを持っているならそれを流用するほうが賢明かもしれません。 またゲームをやるかわからないのであれば、グラフィックボードの購入を今はやめておくのも賢い判断だと思います。

GPU 内臓モデルのほうがいくらか値段は高くなります。 しかし、グラフィックボード故障時や各パーツの不具合対応時にも、最小構成で画面を映すことができるため、保険として持っておくには安い買い物だと私は思うのです。 そんなこともあり、今回は GPU 内臓モデルを使用し、グラフィックボードは流用する前提にしていきます。

ここまでの絞り込みで以下の 4 モデルが対象となりました。

  • Core i9 12900K / 12900(P Core × 8、E Core × 8、24 論理コア)
  • Core i7 12700K / 12700(P Core × 8、E Core × 4、20 論理コア)

価格との相談

これらはいずれも私の用途に合う CPU ですので、あとは価格との相談で決めていきます。 国内の PC 専門店の価格を見ると、おおよそ以下のような感じでした。

モデル 価格
Core i9 12900K 約74,000円
Core i9 12900
Core i9 12700K 約52,000円
Core i9 12700 約49,000円

12900 無印はまだ販売されていないので価格はわかりませんが、定価を見る限り、リリース直後は 6万円後半くらいになるのではないかと思います。 また 12700 無印はリリース間もないため、ほとんと値引きされていない状態です。 12700K はすでに値下がり始めているので、本日時点で見ると 12700K のコスパの良さが目立ちます。




Core i7 12700K を採用

最終的に Core i7 12700K を採用することにしました。 私の用途には十分な性能を持っていそうです。 また熱という意味でも Core i9 12900K より運用しやすそうです。

もう少し時間がたって、 12700 や 12900 の無印版の価格が大きく下がるようなら、その時はそちらを選択する可能性もありそうです。 本日時点では未発売だったり、価格がこなれていないこともあり、選択肢から外さざるをえなかったのが実情ですね。

次回はマザーボードの選択編です。

*1:PentiumCeleron はニーズに合わないので最初から除外します。

Blazor WebAssembly アプリケーションを Azure App Service にデプロイして Azure AD で保護する

f:id:masatsuna:20220104234505p:plain

新年 1 つ目のポストは、昨年末すごくはまった内容をまとめてみようと思います。

やりたいこと

.NET ベースの Blazor WebAssembly アプリケーションを ASP.NET Core のアプリケーションでホストして、 Azure App Service に発行します。 こいつに対して Azure AD ( B2C ではない方) で認証をかけていきます。

Blazor WebAssembly のアプリケーションは、 Azure Static Web Apps を使うケースが多いかもしれません。 しかし、規模の大きなシステムだと「複雑な業務要件」という名の低性能機能が紛れ込んだりして、 Azure Functions は安心して使えなかったりします。 そうなると結局 App Service Plan 上で動かすなんて言うことになったりするんですよね。 規模が大きくなればなるほど、こういった部分はコントロールできなくなっていくのがつらいところです。

環境

Blazor アプリケーションを作る

ASP.NET Core のアプリケーションをバックエンドにもつ Blazor WebAssembly のアプリケーションは、 Visual Studio のテンプレートを使うと簡単にひな形を作ることができます。 まずは [Blazor WebAssembly アプリ] を選択しましょう。

f:id:masatsuna:20220102121838p:plain

今回は Azure AD 認証を組み込むので、 [認証の種類] を [Microsoft ID プラットフォーム] に設定します。 またバックエンドの Web API は Azure App Service にホストするので、 [ASP.NET Core でホストとされた] にもチェックを入れてプロジェクトを生成します。

f:id:masatsuna:20220102121928p:plain

生成が終わると、以下のような 3 つのプロジェクトが作成されるはずです。

f:id:masatsuna:20220102122050p:plain

プロジェクト 概要
[*.Client] プロジェクト Blazor WebAssembly のソースコードが含まれています。クライアント側の処理本体です。
[*.Server] プロジェクト バックエンドの Web API を含む、 ASP.NET Core のアプリケーションです。ローカルで実行する場合はこのプロジェクトを実行します。
[*.Shared] プロジェクト 主にバックエンドの公開する Web APIDTO*1 を格納するプロジェクトです。サーバーサイドとクライアントサイドで共有したい簡単な処理もここに置きます。

Azure AD 認証の設定を確認する

ここまでの設定で生成したアプリケーションには、 Azure AD 認証に必要なコードや設定が、ダミー値で含まれています。 重要な設定項目について簡単に触れておきます。

サーバーアプリケーションの appsettings.json

Web API を保護するための設定が appsettings.json にあります。 後ほど Azure Portal で設定した値をここに設定していくことになります。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "qualified.domain.name",
    "TenantId": "22222222-2222-2222-2222-222222222222",
    "ClientId": "11111111-1111-1111-11111111111111111",
    "Scopes": "access_as_user",
    "CallbackPath": "/signin-oidc"
  },
  // 後略
}

クライアントアプリケーションの appsettings.json

こちらはクライアント側アプリケーションを保護するための設定です。 [*.Client] プロジェクトのルートの wwwroot ディレクトリ内にファイルがあります。 こちらも後ほど Azure Portal で設定した値を設定します。

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/22222222-2222-2222-2222-222222222222",
    "ClientId": "33333333-3333-3333-33333333333333333",
    "ValidateAuthority": true
  }
}

クライアントアプリケーションの Program.cs

[*.Client] プロジェクトの Program.cs にも設定があります。 今回の構成では、 AddMsalAuthentication メソッド内のオプション設定を変更することになります。

using BlazorApp.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddHttpClient("BlazorApp.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("BlazorApp.ServerAPI"));

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("api://api.id.uri/access_as_user");
});

await builder.Build().RunAsync();

なお今回は動作検証が目的ですので、上記の設定ファイルやコードに設定値をべた書きします。 ローカル開発のことや、各種設定値を直接設定ファイルに保存するセキュリティ上の問題は全く考慮していませんので注意してください。

Azure に実行環境を構築する

アプリケーションの生成が完了したら、 Azure 上に実行環境を作っていきます。 今回は Windows の Azure App Service 上にアプリケーションを配置するので、以下のような設定で作ってみます。

f:id:masatsuna:20220102213549p:plain

リソースができたら、 URL を控えておきましょう。

Azure AD を設定する

次に Azure AD の設定を行っていきます。 クライアントアプリケーションとサーバーアプリケーションを Azure AD にアプリ登録して、クライアントアプリケーションからサーバーアプリケーションの呼び出しを許可するように設定しましょう。

サーバー API のアプリケーションを登録する

Azure Portal で [Azure Actice Directory] のブレードを開き、 [アプリ登録] のメニューから [新規登録] を行いましょう。 アプリケーションの [名前] を適当に設定して、 [サポートされているアカウントの種類] を [この組織ディレクトリのみに含まれるアカウント] に設定します。 [リダイレクト URI] は [Web] を選択して、リダイレクト先の URL は未設定にします。

f:id:masatsuna:20220102215413p:plain

設定が終わったら、画面下部の [登録] ボタンを押下します。

正常に登録ができると、登録したアプリの詳細が表示されるので、以下の設定値を手元に控えましょう。 どちらも GUID 値です。

  • アプリケーション (クライアント) ID
  • ディレクトリ (テナント) ID

続いて [API の公開] メニューに移動し、 [Scope の追加] を押下します。 [アプリケーション ID の URI] が表示されるので、控えておきましょう。 画面下部の [保存してから続ける] を押下します。

f:id:masatsuna:20220102230942p:plain

[スコープ名] 、 [管理者の同意の表示名] 、 [管理者の同意の説明] を設定します。 [スコープ名] は後で利用するため控えておきましょう。 [状態] を [有効] にして、画面下部の [スコープの追加] を押下します。

f:id:masatsuna:20220103000407p:plain

クライアントアプリケーションを登録する

続いてクライアントアプリケーションも Azure AD に登録します。 [アプリ登録] のメニューから [新規登録] を行います。 アプリケーションの [名前] を適当に設定して、 [サポートされているアカウントの種類] を [この組織ディレクトリのみに含まれるアカウント] に設定します。 [リダイレクト URI] は [シングルページ アプリケーション (SPA)] を選択して、リダイレクト先の URL は [<Azure App Service の URL>/authentication/login-callback] に設定します。

f:id:masatsuna:20220103005205p:plain

設定が終わったら、画面下部の [登録] ボタンを押下します。

正常に登録ができると、登録したアプリの詳細が表示されるので、以下の設定値を手元に控えましょう。

  • アプリケーション (クライアント) ID

続いて [API のアクセス許可] メニューに移動し、 [アクセス許可の追加] を押下します。 [自分の API] を選択して、先ほど作成したサーバー API のアプリケーションを選択します。 作成したスコープを選択して、 [アクセス許可の追加] を押下します。

f:id:masatsuna:20220103010015p:plain

[<テナント名> に管理者の同意を与えます] ボタンを押下して、同意を付与します。

f:id:masatsuna:20220103010936p:plain

Azure AD の情報取得

プライマリドメインの値を控えておきましょう。 [Azure Active Directory] ブレードの [概要] メニューの画面で確認できます。 通常は 「xxxxxx.onmicrosoft.com」となります。

設定値の修正とコードの修正

Azure Portal から取得した各情報を、テンプレートのJSONやコードに反映していきます。

サーバーアプリケーションの appsettings.json の設定

DomainTenantIdClientIdScopes の値を設定します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "<プライマリドメインの値>",
    "TenantId": "<ディレクトリ (テナント) ID の GUID 値>",
    "ClientId": "<サーバー API のアプリケーションのアプリケーション (クライアント) ID>",
    "Scopes": "<サーバー API のアプリケーションのスコープ名>",
    "CallbackPath": "/signin-oidc"
  },
  // 後略
}

クライアントアプリケーションの appsettings.json の設定

AuthorityClientId の値を設定します。

  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/<ディレクトリ (テナント) ID の GUID 値>",
    "ClientId": "<クライアントアプリケーションのアプリケーション (クライアント) ID>",
    "ValidateAuthority": true
  }

クライアントアプリケーションの Program.cs の設定

DefaultAccessTokenScopes に以下のように設定します。

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("<サーバー API のアプリケーションのアプリケーション ID の URI>/<スコープ名>");
});

なおここまでの手順は、以下のリンク先にも解説があります。

docs.microsoft.com

アプリケーションの配置

アプリケーションの修正が終わったら、 [*.Server] のプロジェクトを発行して、 Azure App Service に配置しましょう。 Release モードで発行するようにしましょう。

f:id:masatsuna:20220104221302p:plain

実行。。。だがしかし

Microsoft の手順では、これで Azure AD 認証が実行できるはずなのですが、動かしてみると多分動かないと思います。 Azure App Service に配置したアプリケーションにブラウザーからアクセスすると、 Blazor のアプリケーションが動いていることは確認できます。 しかし、右上の [Log in] リンクを押下すると、以下のような画面になってしまいます。

f:id:masatsuna:20220104221524p:plain

画面のメッセージは以下のように表示されています。

There was an error trying to log you in: 'Cannot read properties of undefined (reading 'toLowerCase')'

このメッセージは、ほとんどのケースで JavaScript の読み込みがうまくできていないときに表示されるものです。 何かしらの処理を呼び出そうとした結果、その処理が存在しないと、このようなメッセージが表示されます。

ブラウザーの開発者ツールを見てみると、コンソールにこんなメッセージが表示されています。

f:id:masatsuna:20220104222458p:plain

info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

以下のトラブルシューティングにも同じようなメッセージについて記載がありました。

https://docs.microsoft.com/ja-jp/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory?view=aspnetcore-6.0#troubleshoot

f:id:masatsuna:20220104222739p:plain

しかし、 Azure Portal から上述の設定箇所を見ても、既定値では問題はない状態になっていると思います。

何が原因なのか

この問題は、 Azure AD 認証に使用する MSAL のクライアントライブラリから連なるライブラリが、トリミングの中で削除されてしまうことにあります。 Blazor WebAssembly は、クライアントに出力するライブラリサイズを削減するために、発行ビルドを行ったタイミングでトリミングが行われます。 本来必要なライブラリがトリミングによって削除されてしまったことで、このような現象が発生しているのです。

docs.microsoft.com

この挙動については、以下の GitHub Issue でも解説があります。

github.com

解決策1:トリミングを無効にする

まずは最も手軽に実施できる、トリミングを無効にする方法で解決してみましょう。 [*.Client] プロジェクトの csproj ファイルを開き、以下のように PublishTrimmed 要素を追加して false に設定します。

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <PublishTrimmed>false</PublishTrimmed>
  </PropertyGroup>

この設定で再度発行を行います。 ブラウザーからアクセスすると、 Azure AD 認証が実行できます。 [Log in] のリンクを押下すると、以下のように Azure AD 認証の画面がポップアップします。

f:id:masatsuna:20220104230355p:plain

正常にログインもできるはずです。

解決策2:MSAL の必要ライブラリが削除されないようにする

続いて、 MSAL の必要ライブラリがトリミングされないように設定する方法で解決してみます。 解決策1 で設定した PublishTrimmed 要素の設定を削除して、以下のように <TrimmerRootAssembly Include="Microsoft.Authentication.WebAssembly.Msal" /> の設定を追加します。

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.1" PrivateAssets="all" />
    <PackageReference Include="Microsoft.Authentication.WebAssembly.Msal" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
    <TrimmerRootAssembly Include="Microsoft.Authentication.WebAssembly.Msal" />
  </ItemGroup>

これで再度発行を行っても、 Azure AD 認証が実行できます。

うまくいかないとき

これらの解決策を実行して、画面がうまく表示できないときは、 Visual Studiodotnet のローカルキャッシュが残ってしまっている影響が考えられます。 ソリューションフォルダ内の bin や obj ディレクトリをいったん削除して、再度発行を行ってみましょう。

どちらがより良い解決策か

PublishTrimmedfalse に設定すると、すべてのトリミングが無効になります。 そのため、解決策2 で示した方法のほうが、良い解決策といえます。

実際にこれら 2 つの解決策を実施して、ブラウザーがダウンロードする HTML やライブラリの合計サイズを比較してみると、以下のようになりました。

手段 サイズ
解決策1(トリミング無効設定) 728KB
解決策2(TrimmerRootAssembly 設定) 676KB

これは、トップ画面をロードするときのダウンロードサイズで比較しています。 純粋なライブラリの量だけではなく、 HTML や CSS などを含むダウンロードサイズであることに注意して下さい。

そのような雑な条件下でも、依存関係にあるライブラリを個別にトリミングしないよう設定した方が、ダウンロードサイズを小さくできました。 パフォーマンスを求めるのであれば、細かな制御が必須であることは明らかです。

まとめ

今回は Blazor WebAssembly のアプリケーションに対して Azure AD 認証をかける方法について解説しました。 Blazor WebAssembly 特有のトリミングにより、ドキュメントに記載されていない挙動に悩まされましたが、問題なく認証をかけることができました。

ローカル開発環境ではうまく動くのに、発行したとたん動かないようなケースは、トリミングを疑ってみるとよいかもしれません。 トリミングの影響かどうか調査する目的なら、 PublishTrimmed の設定を false にするのがお手軽な方法です。 トリミングの影響であることが確定したら、細かなオプションを活用して、トリミングによるパフォーマンスアップと、機能性の担保を両立させる設定を探すのが定石だと思います。

なおトリミングには、今回ご紹介した以外に様々な設定があります。 詳細は以下のドキュメントを参照してください。

docs.microsoft.com

*1:Data Transfer Object

小ネタ:Visual Studio のテストの成功と失敗で一喜一憂する

f:id:masatsuna:20211226234543p:plain

Visual Studio 2019 の 16.9 あたりの更新から、単体テストの実行完了時に音を鳴らすことができるようになりました。 あまり良いとは言えませんが、テストの実行に時間を要するようなケースでは、テストを流しながら別の作業をすることもあるのではないでしょうか。 テストの実行完了を音で判断できるので、並列作業が非常にはかどります。

環境

今回は上記の環境での設定例を示しますが、 Windows 10 や Visual Studio 2019 16.9 以降でも、ほとんど同じ方法で設定可能です。

設定方法

  1. [ツール] メニュー > [オプション] を選択します。

  2. 左側メニューから [テスト] > [全般] を選択します。

  3. 右側ペインの [サウンドの構成] ボタンを押下します。 f:id:masatsuna:20211226232233p:plain

  4. [サウンド] ウィンドウの [プログラム イベント] の一覧から [Microsoft Visual Studio] を探し、その中にある [テストの実行失敗] または [テストの実行成功] を選択して、 [サウンド] のドロップダウンから鳴らしたい音を選択します。 [参照] ボタンを押下すると、ローカルマシン内のサウンドファイル (*.wav) を使うこともできます。 f:id:masatsuna:20211226232540p:plain

  5. 設定が終わったら [OK] ボタンを押下して保存します。

  6. Visual Studio の [オプション] ダイアログに戻り、 [テストの実行が完了したら音を鳴らす] にチェックを入れて、 [OK] ボタンを押下します。 f:id:masatsuna:20211226233159p:plain

これでテストの成功・失敗にあわせて好きなサウンドを鳴らすことができます。

まとめ

非常に地味な機能なのですが、裏側でテストを走らせることの多い私には非常に重宝する機能です。 テストが終わったことに気づいていなかった、みたいな無駄時間を減らすことにつながっています。

好きなサウンドを選べるのもうれしいです。 テスト成功時はテンションの上がるサウンドを、テスト失敗時は恐怖心をあおるサウンドを設定して、開発作業を楽しんでいます。

XUnit で Null のフロー解析が警告を出す問題に対処する

f:id:masatsuna:20211224085633p:plain

※本稿は 2021/12/8 時点の情報に基づいています。

2021 年 11 月は .NET のリリース祭り

Visual Studio 2022 とか C# 10 とか .NET 6 とか、 .NET 関連のリリースが 11 月に一気に押し寄せてきました。 手元のプロジェクトもいくつか .NET 6 への対応を始めているのですが、多くの新機能の中で最も役に立っている実感があるのが Null 許容参照型です。 何気なく書いていたコードの中に、 Null 参照になってしまう可能性があるコードって結構あるんだなーと。 お前がポンコツだからいけないんだろ、という話は置いといて。

XUnit と Null 許容参照型

そんな Null 許容参照型ですが、 XUnit の最新の安定板リリースである 2.4.1 では、 Null 許容参照型に対する考慮が入っていません。 テストプロジェクトで Null 許容参照型のフロー解析を使うと、いたるところで警告が出るはずです。

環境

検証

例えば以下の SampleMethod をリフレクションで探すようなテストを書いてみます。

public class SampleClass
{
    public void SampleMethod()
    {
    }
}

テストコードは以下のようになります。

public class MethodInfoTest
{
    [Fact]
    public void Test1()
    {
        var type = typeof(SampleClass);
        var methodInfo = type.GetMethod("SampleMethod");

        Assert.NotNull(methodInfo);
        Assert.Equal("SampleMethod", methodInfo.Name);
    }
}

このテストプロジェクトで Null 許容参照型のフロー解析を有効にしていると、 Xunit 2.4.1 ではフロー解析の警告が出ます。

f:id:masatsuna:20211224084505p:plain

Assert.NotNull で null ではないことが確定しているので、この警告はいやです。

解決策

Xunit 2.4.2-pre.12 にアップデートしましょう。 このバージョンからフロー解析のための属性がテストメソッドに付与されるようになっており、警告が出ないようになりました。

f:id:masatsuna:20211224084825p:plain

サンプルコード

サンプルコードは以下から参照できます。

github.com

Azure Pipelines で SQL Server LocalDB を用いたテストを実行する

f:id:masatsuna:20211204142845p:plain

Azure Pipelines では、ビルドサーバーを大きく 2 つの種類から選択できます。 1 つ目は「MS-Hosted Agent」と呼ばれるもので、雑に言うとマイクロソフトさんが準備したビルドマシンをオンデマンドで借用する方式です。 2 つ目は「Self Hosted Agent」と呼ばれるもので、自分で用意したマシンをビルドマシンとして登録して利用する方式です。

MS-Hosted Agent は、特に自分で何か用意する必要はなく、非常にお手軽に利用できます。 マイクロソフトさんが提供しているエージェントの中から、利用したいものを選択する形式です。 そのため、万人が必要とするソフトウェア以外、エージェントにはインストールされていません。

今回は MS-Hosted Agent で SQL Server LocalDB を用いたテストを実行する方法について解説します。

環境

  • SQL Server LocalDB(特にバージョン問わず)
  • .NET 6
  • Visual Studio 2022
  • Entity Framework Core 6.0.0
  • xUnit 2.4.1
  • Azure Pipelines ( MS-Hosted Agent windows-2022)

サンプルコード

本稿でご紹介するサンプルコードは、以下から全量を参照できます。 記事内では重要な部分のみ抜粋して掲載しますので、適宜参照してください。

github.com

Agent の SQL Server LocalDB を起動する

実は MS-Hosted Agent の windows-2022 マシンには、 SQL Server LocalDB がちゃんとインストールされています。 ただ、起動していない状態になっています。 Azure Pipelines の YAML ファイル内で、 SQL Server LocalDB を起動するスクリプトを実行しましょう。

- task: CmdLine@2
  displayName: 'SQL Server LocalDB の起動'
  inputs:
    script: |
      sqllocaldb start mssqllocaldb

これで SQL Server LocalDB が起動します。

データベースを構築する

SQL Server LocalDB を起動しただけでは、サーバーは空の状態です。 ここにテスト用のデータベースを構築していきます。 今回はプロジェクトに含めてある Entity Framework Core のマイグレーションを実行して、データベースを構築してみます。

Entity Framework Core のマイグレーションを実行するためには、 Entity Framework Core ツールをインストールしないといけません。 今回の例では DotNetCoreCLI@2 のタスクを使ってインストールしています。

インストールしたら、同じく DotNetCoreCLI@2 のタスクを使ってマイグレーションを適用します。

- task: DotNetCoreCLI@2
  displayName: 'dotnet-ef のインストール'
  inputs:
    command: 'custom'
    custom: 'tool'
    arguments: 'install --global dotnet-ef'
- task: DotNetCoreCLI@2
  displayName: 'テスト用データベースの構築'
  inputs:
    command: 'custom'
    custom: 'ef'
    arguments: 'database update'
    workingDirectory: '$(Build.SourcesDirectory)/TestWithLocaldb/src/TestWithLocaldb.DataAccess/'

これでデータベースの構築ができます。

今回は Entity Framework Core のマイグレーションを用いてデータベースを構築しましたが、 SQL ファイルを実行してもデータベースを構築できます。 その場合は以下のように、 SQL Server LocalDB を起動した直後に sqlcmd をたたいて構築するのが良いと思います。

- task: CmdLine@2
  displayName: 'SQL Serverセットアップ'
  inputs:
    script: |
      sqllocaldb start mssqllocaldb
      sqlcmd -S (localdb)\MSSQLLocalDB -E -i $(Build.SourcesDirectory)/SqlServerSample/sqls/InitializeDatabase.sql

※このコードは、サンプルコードの GitHub リポジトリに含まれていません。

テストの実行

データベースの構築が終わったら、テストを行うタスクを走らせましょう。

- task: DotNetCoreCLI@2
  displayName: '単体テストの実行'
  inputs:
    command: 'test'
    projects: '$(TestProjects)'
    arguments: '--configuration $(BuildConfiguration) --collect "XPlat Code coverage" -- RunConfiguration.DisableAppDomain=true'  

ビルドパイプラインを実行してみる

今回はちゃんとデータベースを使ったテストができるか確認することを目的にして、簡易な確認を行ってみます。 データベースにデータをくべて、その値を取得するというあまり意味のないテストです。

namespace TestWithLocaldb.DataAccess.Test;

public class UnitTest
{
    [Fact]
    public void データベースを利用したテスト()
    {
        InitializeDatabase();

        using var dbContext = new ProductDbContext();
        var products = dbContext.Products
            .Where(p => p.Publisher == "秋田")
            .OrderBy(p => p.Id)
            .ToList();
        Assert.Collection(products,
            product =>
            {
                Assert.Equal(2, product.Id);
                Assert.Equal("きりたんぽ", product.Name);
            },
            product =>
            {
                Assert.Equal(3, product.Id);
                Assert.Equal("なまはげ", product.Name);
            });
    }

    private static void InitializeDatabase()
    {
        var connectionString = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=sample-database;Integrated Security=True;";
        using var connection = new SqlConnection(connectionString);
        using var deleteCommand = connection.CreateCommand();
        deleteCommand.CommandText = "DELETE FROM [dbo].[Products];";
        using var insertCommand = connection.CreateCommand();
        insertCommand.CommandText = "INSERT [dbo].[Products] ([Id], [Name], [Publisher]) VALUES (1, N'りんご', N'青森');" +
            "INSERT [dbo].[Products] ([Id], [Name], [Publisher]) VALUES (2, N'きりたんぽ', N'秋田');" +
            "INSERT [dbo].[Products] ([Id], [Name], [Publisher]) VALUES (3, N'なまはげ', N'秋田');";
        connection.Open();
        deleteCommand.ExecuteNonQuery();
        insertCommand.ExecuteNonQuery();
    }
}

このテストを Azure Pipelines 上で実行してみると、ちゃんと実行できていることが確認できます。

f:id:masatsuna:20211204141300p:plain

まとめ

今回は MS-Hosted Agent を使って、 SQL Server LocalDB に依存したテストを実行してみました。 データベースに依存したテストを大量に実行するのはあまりおすすめできませんが、限られたテストケースを実行するのであれば、十分実用に耐えられるのではないでしょうか。

Entity Framework Core でエンティティの変更記録を確認する方法

f:id:masatsuna:20211201000255p:plain

前提となる環境

Change Tracker とは何か

Entity Framework Core は、 Change Tracker という仕組みを持っています。 Change Tracker は、 DbContext を経由して取得したデータに対して、更新や削除、追加などの操作を行った記録を保持する役割を持ちます。 DbContext.SaveChanges() メソッドを呼び出しただけで、 DbContext に対して行った変更がすべて反映できるのは、 Change Tracker のおかげといっても過言ではありません。

Change Tracker は思わぬ不具合を生みやすい

この Change Tracker という仕組みは、わかって使うと非常に便利な仕組みです。 しかし、ロジック内で DbContext から取得したオブジェクトの値を不用意に書き換えてしまうと、 Change Tracker の追跡対象になってしまって、意図しない更新クエリが発行されてしまいます。 このようなケースでは、 Change Tracker がどのような状態になっているか、意図した変更記録が残されているか、デバッグしながら確認することになります。

Change Tracker が追跡している変更記録を確認する

Change Trakcer の状態を確認するには、 DbContext.ChangeTracker.DebugView.LongView または DbContext.ChangeTracker.DebugView.ShortView を参照しましょう。 現在の Change Tracker の状態をすべて表示してくれます。

LongView のほうは、各レコードのカラム単位まで、どのような状態になっているかを表示できます。 ShortView はレコードの単位でしか把握することができません。

実際に動かしてみる

DebugView の動作を確認してみましょう。 今回は以下のような DB モデルを作りました。

namespace ChangeTrackerConfirm.Models;

public class Category
{
    public Category()
    {
        this.Name = string.Empty;
        this.Products = new HashSet<Product>();
    }

    public long Id { get; set; }
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}

public class Product
{
    public Product() => this.Name = string.Empty;

    public long Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public long CategoryId { get; set; }
    public Category? Category { get; set; }
}

DbContext は以下のようにしています。

using Microsoft.EntityFrameworkCore;

namespace ChangeTrackerConfirm.Models;

public class SampleDbContext : DbContext
{
    public SampleDbContext() { }

    public DbSet<Category> GetCategories { get; set; }
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        ArgumentNullException.ThrowIfNull(optionsBuilder);
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=SampleDatabase;Integrated Security=True");
        }
    }

    // 後略

このような DbContext に対して、データの取得と変更、新規追加を行いながら、DbContext.ChangeTracker.DebugView.LongView をコンソールに出力してみます。 カテゴリー ID が 1 のデータを取得して、全レコードの価格を 1.1 倍に更新し、新たなレコードを 1 件追加しています。

using ChangeTrackerConfirm.Models;

using var dbContext = new SampleDbContext();
ShowChangeTracker(1, dbContext);

var products = dbContext.Products
    .Where(p => p.CategoryId == 1)
    .ToList();
ShowChangeTracker(2, dbContext);

foreach (var product in products)
{
    product.Price = product.Price * 1.1M;
}

ShowChangeTracker(3, dbContext);

var newProduct = new Product
{
    Name = "Entity Framework の本",
    Price = 2800,
    CategoryId = 1,
};
dbContext.Products.Add(newProduct);
ShowChangeTracker(4, dbContext);

dbContext.SaveChanges();
ShowChangeTracker(5, dbContext);

void ShowChangeTracker(int count, SampleDbContext dbContext)
{
    Console.WriteLine($"= No.{count} ======================");
    Console.WriteLine(dbContext.ChangeTracker.DebugView.ShortView);
    Console.WriteLine("=============================");
}

実行結果は以下のようになります。

= No.1 ======================

=============================
= No.2 ======================
Product {Id: 1} Unchanged
  Id: 1 PK
  CategoryId: 1 FK
  Name: 'C#の本'
  Price: 2000
  Category: <null>
Product {Id: 2} Unchanged
  Id: 2 PK
  CategoryId: 1 FK
  Name: 'F#の本'
  Price: 1800
  Category: <null>

=============================
= No.3 ======================
Product {Id: 1} Unchanged
  Id: 1 PK
  CategoryId: 1 FK
  Name: 'C#の本'
  Price: 2200.0 Originally 2000
  Category: <null>
Product {Id: 2} Unchanged
  Id: 2 PK
  CategoryId: 1 FK
  Name: 'F#の本'
  Price: 1980.0 Originally 1800
  Category: <null>

=============================
= No.4 ======================
Product {Id: -9223372036854774807} Added
  Id: -9223372036854774807 PK Temporary
  CategoryId: 1 FK
  Name: 'Entity Framework の本'
  Price: 2800
  Category: <null>
Product {Id: 1} Unchanged
  Id: 1 PK
  CategoryId: 1 FK
  Name: 'C#の本'
  Price: 2200.0 Originally 2000
  Category: <null>
Product {Id: 2} Unchanged
  Id: 2 PK
  CategoryId: 1 FK
  Name: 'F#の本'
  Price: 1980.0 Originally 1800
  Category: <null>

=============================
= No.5 ======================
Product {Id: 1} Unchanged
  Id: 1 PK
  CategoryId: 1 FK
  Name: 'C#の本'
  Price: 2200.0
  Category: <null>
Product {Id: 2} Unchanged
  Id: 2 PK
  CategoryId: 1 FK
  Name: 'F#の本'
  Price: 1980.0
  Category: <null>
Product {Id: 12} Unchanged
  Id: 12 PK
  CategoryId: 1 FK
  Name: 'Entity Framework の本'
  Price: 2800
  Category: <null>

=============================

No.1 のタイミングでは、 DbContext のオブジェクトを作っただけなので、 Change Tracker は何も追跡しておらず、データも空っぽです。

No.2 は、データベースに対して問い合わせを行った後のタイミングで表示しています。 Change Trakcer は、取得したデータを追跡し続けます。 よってこのタイミングでは、追跡対象のオブジェクトとして認識されているものの、データは変更していないため、 Unchanged とマークされます。

No.3 は、価格のデータをすべて 1.1 倍した後のタイミングで表示しています。 Price の状態を見ると、「Price: 2200.0 Originally 2000」のような記載になっており、データを 2000 から 2200 へ、 1.1 倍した様子を確認できます。

No.4 は、新たな商品データを追加した後のタイミングで表示しています。 「Entity Framework の本」のレコードが Added にマークされており、新規追加されたレコードであることを確認できます。 今回 Id はデータベース側で採番するよう設定しているため、 Id は「PK Temporary」が設定され、値も long の最小値が入っています。

No.5 は、 DbContext.SaveChanges() メソッドを呼び出した後のタイミングで表示しています。 ここまでに行ってきたデータの編集と新規レコードの追加は、 SaveChanges メソッドを呼び出すことでデータベースに反映されます。 そのため、 DbContext 内のデータはすべて Unchanged 状態に戻されます。 また新規追加したレコードは、データベース側で採番した Id の値が書き戻されていることも確認できます。

まとめ

今回は Entity Framework Core の Change Tracker の情報を確認する方法について解説しました。 Change Tracker でハマったときは、今回解説した情報を参考に、デバッグしてみてください。

サンプルコード

本稿で紹介したサンプルコードは、以下からダウンロードできます。

github.com

AMD プロセッサでも Hyper-V を入れ子にできるようになる話

f:id:masatsuna:20211019003325p:plain

以前こんな記事を書きました。

tsuna-can.hateblo.jp

今まで Hyper-V仮想マシン内にさらに Hyper-V を立ち上げたり、 Docker を立ち上げたり、ということが AMD プロセッサではできませんでした。 しかし、ようやくと言うか、ついにと言うか、 AMD プロセッサでも Hyper-V入れ子ができるようになるそうです。

念のため歴史を紐解く

もともと AMD プロセッサでは Hyper-V入れ子はできなかったのですが、以下のブログポストにもある通り、 Windows 10 の Insider 向けにこの制限が解除される動きがありました*1

https://techcommunity.microsoft.com/t5/virtualization/amd-nested-virtualization-support/ba-p/1434841

長らくこの機能は Insider 向けにのみ提供されてきましたが、 Windows 11 と Windows Server 2022 から、ついに一般向けにもリリースされるようです。

詳細が知りたい場合は英語版のページを見る

この Hyper-V入れ子については、まだ日本語ドキュメントが整備されていません。 詳細が知りたい方は、以下の英語版ページを参照してください。

docs.microsoft.com

AMD プロセッサの場合、少々条件がきつめです。 OS の最新化が避けられないようです。 記載を抜粋しておきます。

AMD EPYC/Ryzen processor or later

Note

The guest can be any Windows supported guest operating system. Newer Windows operating systems may support enlightenments that improve performance.

もうしばらくは様子見

今回は AMD プロセッサでも Hyper-V入れ子ができるようになる話をご紹介しました。 ホスト OS を Windows 11 にあげないといけないので、2021 年 10 月現在は少々ハードルが高い条件に見えます。 Ryzen のお高めのプロセッサだと、 Windows 11 が性能をフルに発揮できない問題が起きています。



これが解消しない限り、メインマシンの OS 更新はできないです。。。 条件が整ってからじゃないとお試しできないのが悲しいところです。

早いところ安心して Windows 11 にアップデートできるようになると良いですね。 もう少しでパッチが出るという話もあるので、そこに期待しましょう。 そしてこの機能には個人的に非常に期待しているので、早く安心して使える環境になってほしいですね。

*1:この話があったので、そのうち AMD プロセッサでも Hyper-V入れ子ができるんだろうとふんで、私は Ryzen にしたのもあります

Windows 11 Pro をディスクからインストールしてみた

f:id:masatsuna:20211006013149p:plain

2021 年 10 月 5 日、 Windows 11 がリリースされました。 私はチキンなので、実利用環境へのインストールはいったんやめて、 Windows 10 Pro 上の Hyper-V に ISO イメージからインストールしてみようと思います。 今回は日本語ローカライズ済みの Windows 11 Pro をインストールします。

環境

ホストマシンは以下の通りです。

仮想マシンを作る

普通に Hyper-V 上で仮想ハードディスク、仮想マシンを作成します。 設定は以下の通りです。

仮想ハードディスク

項目 設定値
ディスクのフォーマット VHDX
ディスクの種類 容量可変
ディスクの構成 新しい仮想ディスク(127GB)

仮想マシン

項目 設定値
世代 第 2 世代
起動メモリ 8GB
動的メモリ 無効
ネットワーク 有効
仮想プロセッサ 8個
SCSIコントローラー [DVD ドライブ] を追加
ブート順 DVD ドライブを最優先に設定

Windows 11 のインストール(TPM 無効の場合)

何かと話題に上っていた TPM ですが、実際に無効状態でインストールしてみて、インストーラーの挙動を確認してみます。 ホストマシンの Hyper-V マネージャーで、 Windows 11 をインストールする前の仮想マシンを電源オフにして、 TPM の設定を確認します。 以下の通り、 [トラステッド プラットフォーム モジュールを有効にする] のチェックを外します。

f:id:masatsuna:20211005221221p:plain

この状態で Windows 11 の ISO イメージを仮想マシンに設定し、ブートしてみます。

f:id:masatsuna:20211005221545p:plain

普通にインストーラーが立ち上がりました。 この部分は Windows 10 のインストーラーと変わらないみたいですね。

そのままインストールを先に進めようとすると。。。

f:id:masatsuna:20211005221626p:plain

TPM が使えないとインストールできないよう制御されていることが確認できました。 ただ、インストールできない理由が何かは教えてもらえません。 ちょっと不親切ですが、こんなことやるのわかっている人だけだと思うので、気にしないでおきます。 たぶん多くの人は Windows 10 からのアップグレードでしょうし、そうであればPC 正常性チェック アプリを使って詳細情報を確認できます。

新しい Windows 11 OS へのアップグレード | Microsoft

Windows 11 のインストール(TPM 有効の場合)

さて、今度はちゃんと TPM を有効にして、 Windows 11 Pro をインストールしてみます。 一旦仮想マシンをシャットダウンして、仮想マシンの設定を変更します。 先ほどオフにしていた [トラステッド プラットフォーム モジュールを有効にする] のチェックを入れておきます。

f:id:masatsuna:20211005221900p:plain

この辺りは以下の記事でも記載しているので参考にしてください。

tsuna-can.hateblo.jp

また物理マシンで挑戦する場合は以下の記事も参考にしてください。 MSI の記事は AMDASUS の記事は Intelチップセットの設定手順です。

tsuna-can.hateblo.jp

tsuna-can.hateblo.jp

プロダクトキーを適切に入力してインストールを始めてみます。

f:id:masatsuna:20211005222247p:plain

ここも Windows 10 のインストーラーと同じような感じですね。

しばらく待っていると、画面が切り替わります。 国を選択します。

f:id:masatsuna:20211005222343p:plain

続いてキーボードの設定を確認します。

f:id:masatsuna:20211005222454p:plain

画像にはありませんが、 2 つ目のキーボード設定はスキップしました。 するとアップデートの確認が走ります。

f:id:masatsuna:20211005222520p:plain

続いて PC の名前設定画面に移ります。 適当な名前を付けて次に進みます。

f:id:masatsuna:20211005222620p:plain

ここで一度再起動が走りました。 自動的に再起動後、用途の設定に移ります。 ドメインに参加するかどうかで選択肢を切り替えます。 個人で利用するならほとんどの場合 [個人用に設定] を選択しましょう。 企業などドメイン環境下で使う場合は [職場または学校用に設定する] を選択します。 本稿では [個人用に設定] の方で進みます。

f:id:masatsuna:20211005222651p:plain

続いてログイン用の MS アカウントの設定です。 この辺は適当にやってください。

f:id:masatsuna:20211005222852p:plain

ローカルアカウントでログインしたい場合は、 [サインイン オプション] のリンクを押下して、 [オフライン アカウント] を選択すると、ローカルアカウントを作成できるようです。 なおローカルアカウントは Windows 11 Home では使えないようです。 Pro にアップデートするか、 MS アカウントを取得しましょう。

続いて PIN の作成を求められます。 適当に作っておきましょう。

f:id:masatsuna:20211005223034p:plain

ただし Hyper-V で使う場合、 PIN を作ってしまうと拡張デスクトップが使えなくなります。 インストール時は PIN の作成が強制みたいなので、一旦拡張デスクトップを無効にしてログインしましょう。 その後、 Windows Hello を無効に設定してから拡張デスクトップを再度有効化するのがよさそうです。 詳細は以下の記事を参照してください。

tsuna-can.hateblo.jp

OneDrive を経由して、過去に使っていたマシンから設定やらを引き継げるみたいです。 今回は余計なお世話なので [新しいデバイスとして設定する] を選択して次に進みます。

f:id:masatsuna:20211005223631p:plain

続いて各種トラッキング系の設定です。 お好きに設定して進んでください。

f:id:masatsuna:20211005224901p:plain

次もトラッキング系の設定です。 お好きに設定して進んでください。

f:id:masatsuna:20211005224946p:plain

続いて OneDrive の使い方に関する設定です。 この設定、実は OneDrive を使うかどうかの設定ではありません。 どちらを選択しても OneDrive はインストールされます。 [OneDrive でファイルのバックアップを行う] を選択すると、デスクトップやドキュメント、ピクチャに保存したものが、勝手に OneDrive にアップロードされます*1。 複数のマシンに同じ MS アカウントでログインする人で、ドキュメント類を PC 間で共有したいニーズがある場合のみ上を選択しましょう。 私はバックアップ・共有したいものだけ選択してアップロードしたいので、 [ファイルのバックアップを行わない] を選択して次に行きます。

f:id:masatsuna:20211005225647p:plain

これでインストール時の設定はすべておしまいで、インストールが終わるのを待つだけです。

f:id:masatsuna:20211005225743p:plain

無事に起動しました。

f:id:masatsuna:20211005230600p:plain

一応バージョンを確認したところ、 22000.194 でした。 前回 Beta チャネルに配信されたものと同等品のようです。

*1:本気でこの設定は余計なお世話だと思います。デフォルトはバックアップなしにしてほしいです。

Hyper-V で画面が表示されない場合の確認項目(Windows 11)

f:id:masatsuna:20211006011733p:plain

以前 Windows 10 の場合の設定方法については記載しています。 今回は Windows 11 の設定箇所を備忘録かねて書いておきます。

tsuna-can.hateblo.jp

拡張セッションを使いたい場合は Windows Hello を無効にする

拡張セッションを使うと、ホスト OS のドライブにアクセスできるようになるので、非常に便利です。 拡張セッションを使いたいのであれば、ゲスト OS 側の設定で、 Windows Hello を無効にしましょう。 PIN を有効にすると Windows Hello が有効になります。 この状態だと拡張セッションが使えません。

Windows 11 をディスクからインストールすると、 PIN の設定が強制されるようです。 Hyper-V 上で実行する場合は、最初にこの設定を変更しないとうまく画面が表示できなくなります。

スタートボタンを右クリックして [設定] を選択します。

f:id:masatsuna:20211006011258p:plain

左側メニューから [アカウント] を選択して [サインイン オプション] を選択します。

f:id:masatsuna:20211006011347p:plain

[セキュリティ向上のため、このデバイスでは Microsoft アカウント用に Windows Hello サインインのみを許可する] のトグルをオフにします。

f:id:masatsuna:20211006011407p:plain

これで拡張セッションが利用できるようになります。

タブの色分け表示機能がよい(Visual Studio 2022 Preview 4)

f:id:masatsuna:20210918143154p:plain

どんな機能か

Visual Studio 2022 Preview 4 でタブの色分け機能が追加されています。 こんな感じで、プロジェクトごとにタブを色分けしてくれて、どのファイルがどのプロジェクトに所属するかわかりやすくなっています。

f:id:masatsuna:20210918122222p:plain

非常にわかりやすくてよいですね。 個人的にとても気に入りました。

なお従来型の水平タブでも同じような色分け表示はできます。

f:id:masatsuna:20210918141625p:plain

ですが見てもらってもわかる通り、垂直タブのための機能と言ってもよさそうです。

この機能をオフにするとどうなるか

オフにすると、以前と全く同じ表示になります。 ちなみに以前まではどうだったかというとこんな感じです。

f:id:masatsuna:20210918141408p:plain

どのファイルがどのプロジェクトの物かちょっとわかりずらいですよね。 色で分けてくれた方が、より視覚的にわかりやすくなって良い感じです。

設定方法

[ツール] メニュー > [オプション] を選択します。

f:id:masatsuna:20210918120021p:plain

左側メニューで [環境] > [タブとウィンドウ] を選択し、右側ペインで [プロジェクト別にドキュメント タブを色分けする] にチェックを入れます。

f:id:masatsuna:20210918122123p:plain

これでタブの色分け機能が利用できます。

なお垂直タブにするためには、 [タブのレイアウト設定] のドロップダウンを変更してください。 こちらの過去記事も参考になるかと思います。

tsuna-can.hateblo.jp

おことわり

この機能はプレビュー版の Visual Studio 2022 に搭載されている機能であり、現在広くサーベイを行っている最中です。 製品版では仕様が変更されている可能性もありますのでご了承ください。