• 検索結果がありません。

データベースプログラミング

N/A
N/A
Protected

Academic year: 2021

シェア "データベースプログラミング"

Copied!
38
0
0

読み込み中.... (全文を見る)

全文

(1)

■ Visual Studio 2010 に依る Windows データベースプログラミング ■ 第1 回 DB アプリのデータソースと成るデータベースの作成 1.SQL Server の DB ファイルをプロジェクトに追加 2.データソース構成ウィザードに依る DB ファイルの追加 3.テーブルの作成とレコードの追加 第2 回 データセットとデータテーブル 1.データセットとは? 2.データセットとデータテーブルの追加 3.データセットとデータテーブルの実体 第3 回 テーブルアダプタの基礎 1.テーブルアダプタとは? 2.テーブルアダプタへのクエリ追加 3.レコード件数の取得を行うクエリの追加 第4 回 ドラッグ&ドロップで作るWindows DB アプリケーション 1.既存データベースの利用 2.DataGridView コントロールの配置 3.デザイナに依り自動的に配置されたコントロールとコンポーネント 第5 回 詳細項目画面の作成とカスタマイズ 1.ドラッグ&ドロップに依る詳細項目画面の作成 2.単純データ連結されたコントロール 3.検索ツールバーの追加

(2)

■ DB アプリのデータソースと成るデータベースの作成 ■ ■ データベースの追加

今回は 1 回目と謂う事で、データベースの作成から始めて観る事にする。SQL Server 2012 Express Edition の機能を利用して、Visual Basic 2010 で DB ファイルに依るデータベースを作成する。更には データベース内にテーブルを作成し、其処に幾つかのレコードも作成する。

1.Windows アプリケーションプロジェクトの新規作成

Visual Basic 2010 又は Visual C# 2010 を起動し、プロジェクトのテンプレートに [Windows フォーム アプリケーション] を選択して、新しいプロジェクトを作成する。 2.プロジェクトへのDB ファイルの追加 先ず、[コントロールパネル] → [システムとセキュリティ] → [管理ツール] → [サービス] で SQL Server (SQLEXPRESS) を開始して置く。 ※ スタートアップの種類が、自動に成って居る場合は、既に、SQL Server (SQLEXPRESS) は始動し て居るので、必要は無い。 但し、開発環境では、スタートアップの種類は、自動ではなく、手動に設定して置いて、必要な時 に起動する事を推奨する。 Windows フォームの画面が開けば、プロジェクトに新しい項目と仕て DB ファイルを追加する。此れ には先ず、次の画面の様にプロジェクトを右クリックして、メニューから [追加] をポイントし [新し い項目] をクリックする。

(3)

[新しい項目の追加] ダイアログが開くので [サービスベースのデータベース] を選択する。此れは SQL Server 用の空の DB ファイル(MDF ファイル)を意味して居る。ファイル名の欄には DB ファイルの ファイル名を指定する(此処ではMyDB.mdf とした)。 ※ 因みに、SQL Server Compact 3.5(SDF ファイル)を使用する場合は、[ローカルデータベース] を 選択する [追加] ボタンをクリックするとプロジェクトに空の DB ファイルが追加されるが、続けて [データソー ス構成ウィザード] が実行される。 [データソース構成ウィザード] の[データベースモデルの選択] では、[データセット] を選択して、[次 へ] をクリックする。

※ 因みに、Entity Data Model(EDM)は、格納される形式に関係無く、データ構造を記述する一連 の概念で、例えば、データをリレーショナルデータベース、テキストファイル、XML ファイル、ス プレッドシート、レポート等、データを多くの形式で格納する場合の問題に対応して居る。 [データソース構成ウィザード] の[データベースオブジェクトの選択] では、データセット名に適切な名 前(此処では、既定のMyDBDataSet とした)を付けて、[完了] をクリックする。 ※ 現時点では、未だ新規作成した許りなので、当然乍、データベースオブジェクトは何も無い。取り 敢えず[完了]ボタンをクリックしてデータソース構成ウィザードを完了する。

(4)

3.プロジェクトに追加されたDB ファイル データソース構成ウィザードで[完了]ボタンをクリックしてDB ファイルの追加を終えると、ソリュ ーションエクスプローラは、次の様な画面に成る。 此処では3 個の項目が追加されて居る。データベース(MDF ファイル)とデータセット(XSD ファイ ル)、然して、接続文字列が保存されて居るアプリケーション構成ファイル(app.config)で有る。 ※ Visual Basic 2010 では、ソリューションエクスプローラでは通常は編集する事の無いファイルが非 表示に成って居る。総てのファイルを表示するとログファイル(LDF ファイル)等も表示される。 猶、アプリケーション構成ファイルで有るapp.config は、コンパイル時には EXE ファイルの生成さ れるフォルダに、<EXE ファイル名>.config と謂う名前でコピーされる。 データソース構成ウィザードの最後で [キャンセル] ボタンを押した場合には、データセットの方は作 成されないが、データベースを追加したのと同様に、プロジェクトの新規項目の追加で [データセット] を追加すれば、何時でも此の項目を追加する事が出来る。此のデータセットに付いては、次回で解説す る。 ■ テーブルの作成とレコードの追加 データベースの中身を観るには、ソリューションエクスプローラで今作成したデータベースをダブルク リックする。然うすると「データベースエクスプローラ」のウィンドウが開く。

(5)

データベースに新しいテーブルを追加するには、「テーブル」の部分を右クリックし[新しいテーブル の追加]を実行する。 テーブルを定義する為の次の様なタブが開くので、テーブルの列項目を定義して行く(此処では取り敢 えず、次の様なテーブルにした)。 [総てを保存] のアイコンをクリックすると([Ctrl]+[S] キーを押すか、メニューから [ファイル] → [< テーブル名>の保存] でも可)、[名前の選択] インプットボックスが開くので、テーブルに名前を付け て保存する(此処では、MyTable とした)。 データベースエクスプローラに戻ると、新しいテーブルが追加された事を確認出来る。作成したテーブ ルは、テーブル名の部分(此処ではMyTable の項目)をダブルクリックするか、右クリックして [テー ブル定義を開く] を実行すれば、再度、編集画面が開いて修正する事が出来る。

(6)

レコードの追加 テーブル名の部分(此処ではMyTable の項目)を右クリックして [テーブルデータの表示] を実行する と、データ入力のタブが開くので、表内にデータを追加して行く。 データを入力して行く(此処では、下図の様なデータを入力した)。 [総てを保存] のアイコンをクリックして、保存して置く。 テーブルに追加したレコードは [テーブルデータの表示] を実行する事に依り、何時でも閲覧、編集す る事が出来る。

(7)

参考:データソース構成ウィザードに依るDB ファイルの追加 DB ファイルをプロジェクトの新規項目と仕て直接追加せず、データソース構成ウィザード而巳を使用 して、データソースと成るDB ファイルをプロジェクトに追加する事も出来る。此れに付いても簡単に 説明して置く。 データソース構成ウィザードを一番初めから実行するには、Visual Basic 2010 のメニューから[デー タ]-[新しいデータソースの追加]を実行する。 [データソース構成ウィザード] の [データソースの種類を選択] で [データベース] を選択して [次へ] ボタンをクリックする。 ※ 猶、此の画面では、アプリケーションのデータソースと仕て、データベース以外にも Web サービス やオブジェクトが選択出来る様に成って居る。 [データソース構成ウィザード] の [データベースモデルの選択] で [データセット] を選択して [次へ] ボタンをクリックする。 [データソース構成ウィザード] の [データ接続の選択] で [新しい接続] ボタンをクリックする。 ※ 因みに、[アプリケーションがデータベースへの接続に使用するデータ接続] のドロップダウンリス トボックスには、此れ迄に利用した DB ファイルに接続する為の接続文字列(に付けられた名前) が列挙される。 右図の様な [接続の追加] ダイアログが開くので データソースとデータベースを設定する。 先ず、データソースの [変更] ボタンをクリック して、]Microsoft SQL Server データベースファイ ル] を選択して [OK] ボタンをクリックする。 ※ 此れで、使用するデータベースが SQL Server 用のDB ファイルで有る事が設定される。 因みに、Microsoft SQL Server Compact 3.5 や Microsoft Access のデータベースを指定す る事も出来る。 次に、データベースファイル名を記述する(此処 では、MyDB とした)。 最後に、[Windows 認証を使用する] のチェックを オンにして、[OK] ボタンをクリックする。 存在しないDB ファイルを指定すると、[作成しま すか?] と謂う問い合わせ画面が表示されるので [はい] ボタンをクリックすると、新しく空の DB ファイルを作成される。 [データソース構成ウィザード] の [データ接続の 選択] の画面に戻り、此等の情報から接続文字列 が生成される。

(8)

■ データセットとデータテーブル ■ ■ プロジェクトにデータセットを追加

前回はVisual Basic 2010 Express Edition を使って、Windows アプリケーションのプロジェクトに SQL データベースを追加し、其のデータベース内にテーブルを作成した。今回は、データベースのレコ ードをWindows フォームのグリッドに表示する手順を順次解説して行く。 前回で、プロジェクトにSQL データベースを新規追加すると、DB ファイルで有る MDF ファイルと同 時にXSD ファイルが自動的に追加された。例えば、DB ファイルの名前を MyDB.mdf と仕た場合には、 XSD ファイルのファイル名は MyDBDataSet.xsd と成る。此の XSD ファイルがデータセット(正確に はデータセットの定義)で有る。 ※ XSD ファイルがプロジェクト内に含まれて居ない場合には、プロジェクトに新しい項目と仕て [デ ータセット] を追加する。此れに依り、XSD ファイルがプロジェクト内に作成される。 ソリューションエクスプローラでデータセットをダブルクリックするとグレーのデータセットデザイ ナが表示される。此れはデータセットの内容を編集する為の物で有る。 ■ データセット内にデータテーブルを作成 データベースエクスプローラからテーブルをデータセットデザイナ上にドラッグ&ドロップする。 ※ データセットデザイナには、データベースエクスプローラからテーブルをドラッグ&ドロップした り、ツールボックスからデータテーブル等のコンポーネントをドラッグ&ドロップする事が出来る。 実際のテーブルと同じ構造を持つデータテーブルを簡単に作成するには、データベースエクスプロ ーラからテーブルをデータセットデザイナ上にドラッグ&ドロップする。此れに依りデータベース からテーブルのスキーマ情報が取得され、データセット内にデータテーブルが作成される。

(9)

※ 此処で作成するデータテーブルは、実際のテーブルの構造と全く同じで有る必要は無く、データテ ーブルに独自に列を追加したり、プログラムで参照しない様な不要な列を削除したり出来る(此処 では、当面はデータテーブルの編集は行わずに其の儘使用する)。 ※ 猶、上図では、データテーブルで有る MyTable の下に MyTableTableAdapter と謂うボックスが付 いて居るが、此れは次回で解説予定のテーブルアダプタ(TableAdapter)で有る。此のテーブルア ダプタがテーブルからレコードを取得して、其れをデータテーブルに格納をする役目を果たすのだ が、今回の処は取り敢えず無視して欲しい。 ※ 今回は、テーブルを 1 個しか作成して居ないが、データベースに複数のテーブルが有る場合には、 複数のデータテーブルを作成する事も出来、テーブル間にリレーションが設定されて居る場合には、 データテーブル間にも自動的にリレーションが設定される様に成って居る。 以上でデータテーブルを含むデータセットが作成出来た。猶、此処で行った事は、プログラムで使用す るデータセットの構造の定義(デザイン)丈で有る。実際に此のデータセットをプログラムで使用する 場合には、此のデータセットの定義を基に、データセットオブジェクトの作成が必要に成る(Visual Basic 2010 の IDE を使えば、其れを行うコードは自動生成される)。 データセットを使った実験 最後に確認の意味も込めて、データセットへのレコードの追加と、グリッドコントロールとデータセッ トのデータ連結を試して観る事にする(未だ今回はデータベースへのアクセスは行わない。手動でデー タセットにレコードを追加して観る)。 此処では、データセットにデータテーブルを作成した状態から始める(MyTable データテーブルが MyDBDataSet データセット内に作成された状態で有る)。 先ず、グリッドコントロールで有るDataGridView コントロールをツールボックスからフォームにドラ ッグ&ドロップする。

(10)

次にフォームをダブルクリックして、下記のコード(Form の Load イベント)を追加する。

Visual Basic

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load

' データセットのインスタンスを作成 Dim Ds As New MyDBDataSet( )

' データセットにレコードを追加

Ds.MyTable.AddMyTableRow( 1, "名前 1", "住所 1", New DateTime(2007, 2, 27)) ' グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = Ds.MyTable End Sub End Class Visual C# using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 {

(11)

public partial class Form1 : Form { public Form1() { InitializeComponent(); }

private void Form1_Load(object sender, EventArgs e) {

// データセットのインスタンスを作成 MyDBDataSet ds = new MyDBDataSet( );

// データセットにレコードを追加

ds.MyTable.AddMyTableRow( 1, "名前 1", "住所 1", New DateTime(2007, 2, 27)); // グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = ds.MyTable } } } ※ 此処ではデータセットの実体で有る MyDBDataSet クラスのインスタンスを作成するコードを最初 に記述して居るが、此の行を記述せずに、ツールボックスに追加されて居るMyDBDataSet と謂う 項目をフォームにドラッグ&ドロップしても良い。此れを行えば、MyDBDataSet オブジェクトを 変数名MyDBDataSet1 と仕て使える様に成る(此れは、Button コントロールをフォームにドラッ グ&ドロップするとボタンが作成され、Button1 と謂う変数名でボタンのインスタンスにアクセス 出来るのと同じで有る)。 此の項目がツールボックスで見付からない場合には、一度プロジェクトをビルドして観る(ツール ボックスの上部に表示される筈で有る)。

※ 猶、Visual Basic 2010 で、デバッグ開始、又は、ビルトすると、MyDBDataSet.Designer.vb で、 コンパイルエラーが発生する事が有る。此の場合は、エラー一覧から、Get に関するエラーを見付 け出し、Get の前の 1 文字を削除すると、総てのエラーメッセージが消え、正常に動作する様に成 る(自動的に生成されるコードなので、バグで有ろう)。 ※ 続く行の AddMyTableRow メソッドは、データテーブルの実体で有る MyTableDataTable クラス(自 動生成されたクラス)で定義されて居るメソッドで有る。 ※ 最後のデータ連結を行って居る部分では、DataGridView コントロールの DataSource プロパティに データテーブルを直接指定して居るが、DataSource プロパティにデータセットを指定して、 DataMember プロパティでデータテーブル名で有る MyTable を指定しても構わない(此方の方が一 般的で有る)。 プログラムを実行すると、下記の様な画面と成る筈で有る。

(12)

■ テーブルアダプタの基礎 ■ ■ データセットデザイナ上のテーブルアダプタ 前回では、データベースから取得したレコードの入れ物と成るデータセット(及び、データテーブル) に付いて解説した。今回は、データベースとデータセットの橋渡し役と成るテーブルアダプタ (TableAdapter)に付いて解説する。 ※ テーブルアダプタは、データベースのテーブルからレコードを取得し、取得したレコードをデータ セット内のデータテーブルに格納する機能を持ったコンポーネントで有る。 前回、データセットをプロジェクトに追加し、データセットデザイナにデータベースエクスプローラか らテーブルをドラッグ&ドロップしてデータテーブルを作成した時に、自動的にテーブルアダプタも作 成されて居た。 データセットデザイナでは、データテーブルMyTable の下に有る MyTableTableAdapter 部分がテーブ ルアダプタを表して居る。 MyTableTableAdapter には、Fill,GetData と謂うクエリが予め自動生成されて居る。テーブルアダプ タのクエリは、テーブルアダプタに実装されて居る呼出可能な機能の単位で有る。 ※ Fill,GetData クエリは、データベースからレコードを取得する処理を行う為の物で有る。此のクエ リで使用される SELECT 文を確認するには、クエリの部分を選択して其のプロパティを表示し、 CommandText プロパティの部分を観る。マウスカーソルをクエリ部分に翳してもツールチップに 依り確認する事が出来る。 猶、プロパティ欄でCommandText プロパティを選択すると右側に表示されるボタンをクリックす ると、[クエリビルダー] が表示され、GUI でクエリを構築する事が出来る。 データテーブル データアダプタ

(13)

クエリを実行してデータをプレビュー Fill,GetData クエリを呼び出すと此の SELECT 文が実行される訳だが、其れに依り何の様な結果が得 られるかは、クエリ部分を右クリックし、メニューから [データのプレビュー] を実行する事に依り事 前に確認する事が出来る([データのプレビュー] ページで [プレビュー] ボタンをクリックする事に依 り、Fill,GetData クエリの実行結果が表示される)。実際には、此の実行結果がデータテーブル MyTableTableAdapter に格納される事に成る。

(14)

■ データテーブルの実体 コードに依るクエリの実行 其れでは、此処で実際に、コードからテーブルアダプタのメソッドを呼び出して観る事にする。前回の 最後にデータセットを使った実験を行ったが、其れと粗似た手順で有る。 先ず、前々図の状態で一度プロジェクトをビルドする。此れで、ツールボックスには MyDBDataSet とMyTableTableAdapter と謂う 2 個のコンポーネントが登録されて居る筈で有る。此等をフォームに ドラッグ&ドロップし、夫々れのName プロパティを daAddress と taAddress に変更して置く。此れ は、データセットとテーブルアダプタのインスタンス名と成る。

次に、フォームをダブルクリックし、下記のコードを入力する(既に記述して居るコードは、削除する か、コメントアウトして置く)。猶、此処ではFill メソッドの方を使用して居る。

Visual Basic

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load ' テーブルアダプタの Fill メソッド呼出 Me.taAddress.Fill(Me.daAddress.MyTable) ' グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = Me.daAddress.MyTable End Sub End Class

(15)

Visual C# using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 {

public partial class Form1 : Form { public Form1() { InitializeComponent(); }

private void Form1_Load(object sender, EventArgs e) { // テーブルアダプタの Fill メソッド呼出 this.taAddress.Fill(this.dsAddress.MyTable); // グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = this.dsAddress.MyTable } } } プログラムを実行して、次の画面の様にデータベースのレコードが表示されれば実験は成功で有る。 続いては、テーブルアダプタに独自にクエリを追加する方法に付いて解説する。

(16)

■ テーブルアダプタへのクエリ追加 テーブルアダプタには、其れと対に成って居るデータテーブル(此処では MyTable データテーブル) と、其の基に成ったデータベースのテーブル(此処ではMyDB データベースの MyTable テーブル)に 関わるクエリを自由に追加する事が出来る。 ※ 実際には、其のデータテーブルやテーブルに無関係のクエリを追加する事も出来る。 条件検索を行うクエリの追加 此処では、次の様なメソッド(ファンクションプロシージャ)と成るクエリを追加して観る。 Visual Basic

Function FillByAddress(ByVal dataTable As MyDBDataSet.MyTableDataTable, _ ByVal address As String) As Integer

Visual C#

int FillByAddress(MyDBDataSet.MyTableDataTable dataTable, string address)

此のメソッドは、第2 パラメータで指定した文字列と一致する address 列の項目を持つレコードを検索 し、其の結果を第1 パラメータで指定したデータテーブルに格納する。

先ず、データセットデザイナでテーブルアダプタを選択し、右クリックして [クエリの追加] を実行す る(クリックする場所に依っては [追加] → [クエリ])。

(17)

[TableAdapter クエリの構成ウィザード] の [コマンドの種類の選択] ページでは、クエリ内で SQL 文 を発行するか、ストアドプロシージャを呼び出すかを選択する事が出来るが、今回は [SQL ステートメ ントを使用する] を選択して、[次へ] ボタンをクリックする。 [TableAdapter クエリの構成ウィザード] の [クエリの種類の選択] ページでは、クエリで実行出来る SQL 文は、予め 5 種のパターンに絞られて居るが、今回は [複数行を返す SELECT] を選択して、[次 へ] ボタンをクリックする。

(18)

[TableAdapter クエリの構成ウィザード] の [SQL SELECT ステートメントの指定] ページでは、クエ リで使用するSELECT 文を記述する。

[テーブルが読み込むデータ] 欄には、テーブルから総てのレコードを取得する SELECT 文が予め記述 されて居るが、此の儘だと、既に有るFill,GetData クエリと全く同一内容のクエリが出来上がり、意味 が無いので、此処でWHERE 句を追加して、次の様な SELECT 文を記述する(@address の部分は外 部から値を指定する名前付きパラメータで有る)。

SQL

SELECT id, name, address, birthday FROM MyTable WHERE address = @address

此処で、直接SELECT 文を書き換えても良いが、クエリビルダを使えば、より確実に SELECT 文を作 成する事が出来る(クエリビルダを使うとGUI に依り SQL 文を作成出来る)。

(19)

クエリビルダを起動するには、[クエリビルダ] ボタンをクリックする。

クエリビルダでは、address の行のフィルタ部分に、= @address と追加すれば、WHERE 句が自動的 に生成される(クエリビルダではSQL の構文に余り詳しくなくても SQL 文を記述出来る)。クエリビ ルダで [OK] ボタンをクリックすると、クエリ構成ウィザードに、結果が反映されて居る。

(20)

クエリ構成ウィザードで [完了] ボタンをクリックすると IDE に戻るので、此処では、メソッドに名前 を付ける為、[次へ] ボタンをクリックする。

[TableAdapter クエリの構成ウィザード] の [生成するメソッドの選択] ページでは、追加するメソッド とメソッド名を指定する。ウィザードでは1 個の SELECT 文に付いて 2 種の形式のメソッドを生成す る事が出来る(此処では、メソッド名をFillByAddress と GetDataByAddress にした)。

※ メソッド名の指定部分では、Fill と GetData の後に予め By が付けられて居て、何に依って SELECT を行ったのかを書き足せば良い様に成って居る。此処では、address 列で絞り込んだので、メソッド 名は素直にFillByAddress と GetDataByAddress にした。後者のメソッドは不要だが、取り敢えず 作成して置いた。 [TableAdapter クエリの構成ウィザード] の [生成するメソッドの選択] ページで [次へ] ボタンをク リックすると、[ウィザードの結果] ページが表示され、ウィザードの結果が確認出来る。[完了] ボタン をクリックしてIDE に戻る。

(21)

クエリ追加後のデータセットデザイナの画面は次の様に成る(FillByAddress, GetDataByAddress (@address) クエリが追加されて居る)。

追加したクエリのプレビュー

クエリが正しく動作するか確認するには、データセットデザイナで今作成したテーブルアダプタを選択 し、右クリックして [データのプレビュー] を実行する。

(22)

今度は、実行するSELECT 文が名前付きパラメータを含んで居るので、[プレビュー]ボタンをクリッ クする前に、パラメータの値と仕て適当な文字列を入力する必要が有る。パラメータの値の欄に、適当 な国名を入力し(此処では、オーストリアと入力した)、[プレビュー] ボタンをクリックする。

然して、今作成したクエリをコードに依り実行する時には、下記の様に成る。

Visual Basic

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load ' テーブルアダプタの FillByAddress メソッド呼出 Me.taAddress.FillByAddress(Me.dsAddress.MyTable, "オーストリア") DataGridView1.DataSource = Me.dsAddress.MyTable ' グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = Me.dsAddress.MyTable End Sub End Class

(23)

Visual C#

private void Form1_Load(object sender, EventArgs e) { // テーブルアダプタの FillByAddress メソッド呼出 this.taAddress.FillByAddress(Me.dsAddress.MyTable, "オーストリア"); DataGridView1.DataSource = this.dsAddress.MyTable; // グリッドとデータテーブルをデータ連結 DataGridView1.DataSource = this.dsAddress.MyTable; } 業務アプリケーションの参照系の処理では、大抵最初にデータの検索(絞り込み)を行うが、其の検索 処理に合わせて此の様なクエリをテーブルアダプタに追加して行く。 猶、自動生成されるFill,GetData( )クエリは、総てのレコードを取得する為の物だが、データセットに 予めレコードを蓄えてから業務を行うモデルでは、レコード件数が多い場合に其の様なクエリを実行し て仕舞うとメモリが大量に消費されて仕舞うので注意が必要で有る。 レコード件数の取得を行うクエリの追加 最後に、レコード件数の取得を行うクエリの作成方法も簡単に説明して置く事にする。先程と同様に仕 てテーブルアダプタで [クエリの追加] を実行し、今度は次の様な手順でCountAll( )クエリを追加する。 1.[コマンドの種類の選択] で、[SQL ステートメントを使用する] を選択する。 2.[クエリの種類の選択] で[単一の値を返す SELECT] を選択する。

3.[SQL SELECT ステートメントの指定] では、予め SELECT COUNT(*) FROM MyTable と記述 されて居るので、[OK] ボタンをクリックする。 4.[関数名の選択] では、[新しい関数の名前] に CountAll と記述して、[次へ] ボタンをクリックする。 5.[ウィザードの結果] では、結果内容を確認して、[完了] ボタンをクリックする。 此れに依り、テーブルアダプタには、CountAll と謂うメソッドが追加される。。 此のCountAll( )クエリを呼び出して、例えばラベルに検索結果を表示するには、下記の様なコードを記 述する。 Visual Basic Label1.Text = Me.taAddress.CountAll( ) Visual C# Label1.Text = this.taAddress.CountAll( ); 因みに、既にデータテーブルに全レコードを取得して居る場合には、下記の様に仕てデータテーブル内 の行数を得る事も出来る。 Visual Basic Label1.Text = Me.dsAddress.MyTable.Rows.Count Visual C# Label1.Text = this.dsAddress.MyTable.Rows.Count;

(24)

■ ドラッグ&ドロップで作るWindows DB アプリケーション ■ 前回迄は、データセット、データテーブル、然して、テーブルアダプタに付いて解説して来た。今回は 愈々、DataGridView コントロールを使ってデータベースの内容をグリッドで表示し、編集出来る様に する迄、話を進める。 既に第2 回の「データセットを使った実験」でも、若干のコードを記述し DataGridView コントロール にデータセットをデータ連結して使用したが、其れは飽く迄も実験的な物で、Windows データベース アプリケーションの本来の構築手順では無い。

何故なら、Visual Studio では、データベースの追加から DataGridView コントロールの追加迄を総て デザイナ上で行える様に成って居る。コードを1 行も記述せずにデータベースアプリケーションを作成 出来るので有る。今回は、其の手順を解説し乍、其の過程で自動的に追加されるコンポーネントやコン トロールに付いて確認して行く。 ■ 既存データベースの利用 本稿では、此処迄、第1 回で作成したデータベース MyDB.mdf を使って来たが、今回は少し趣向を変 えて、既存のデータベースファイル(以降、DB ファイル)を取り込み、其れに対するテーブルアダプ タ迄を作って観る事にする。 DB ファイルのダウンロード 先ずはDB ファイルを用意する。今回は、マイクロソフトが配布して居るサンプルデータベースを以下 のサイトからダウンロードして使用する。此れはSQL Server 2000 用のデータベースだが、SQL Server 2005 Expression 以降でも問題無く利用出来る様で有る(2014/9/17 現在ダウンロード可)。

Northwind and pubs Sample Databases for SQL Server 2000(SQL Server 2000) ファイル名:SQL2000SampleDb.msi ※ 因みに、SQL Server 2005 以降用にはサンプルデータベースと仕て新しい AdventureWorks データ ベースも用意されて居るが、構成が若干複雑に成って居る為、今回は採用しない事にした。猶、此 れは、下記のページからダウンロード出来る。 http://sqlserversamples.codeplex.com/releases/view/4000(SQL Server 2005) SqlServerSamples.msi(32bit 用) SqlServerSamples_x64.msi(64bit 用) http://sqlserversamples.codeplex.com/releases/view/30803(SQL Server 2008) SQL2008.All_Product_Samples_Without_DBs.x86.msi(32bit 用) SQL2008.All_Product_Samples_Without_DBs.x64.msi(64bit 用) http://sqlserversamples.codeplex.com/releases/view/72278(SQL Server 2008R2) SQL2008.All_Product_Samples_Without_DBs.x86.msi(32bit 用) SQL2008.All_Product_Samples_Without_DBs.x64.msi(64bit 用) 上記のサイトからSQL Server 2000 用のサンプルデータベースで有る SQL2000SampleDb.msi をダウ ンロードして実行すると、C:¥SQL Server 2000 Sample Databases に以下の 2 種類の DB ファイルが 展開される。

・NORTHWND.MDF(Northwind データベース) ・PUBS.MDF(Pubs データベース)

(25)

DB ファイルの追加 続いては、プロジェクトにDB ファイルを追加し、其のデータベースからデータセット、然して、テー ブルアダプタを作成する。 先ず、[コントロールパネル] → [システムとセキュリティ] → [管理ツール] → [サービス] で SQL Server (SQLEXPRESS) を開始して置く。 ※ スタートアップの種類が、自動に成って居る場合は、既に、SQL Server (SQLEXPRESS) は始動し て居るので、必要は無い。 但し、開発環境では、スタートアップの種類は、自動ではなく、手動に設定して置いて、必要な時 に起動する事を推奨する。 此れ迄は、DB ファイルをプロジェクト内に新規作成したが、既存の DB ファイルに付いては、其れを プロジェクト内に追加する。此れには、新規作成した Windows アプリケーションのプロジェクトをソ リューションエクスプローラ上で右クリックし、[追加] - [既存の項目] を実行して [既存項目の追加] ダイアログを開く。 [既存項目の追加] ダイアログでは、[ファイルの種類] を [データファイル (*.xsd; *.xml; *.mdf; *.mdb)] に切り替えて、前述の PUBS.MDF を指定する。 [既存項目の追加] ダイアログを閉じるとデータソース構成ウィザードが起動するので、[データベース モデルの選択] ページでは、データセットを選択して、[OK] ボタンをクリックする。 ※ 此の時点で、SQL Server (SQLEXPRESS) のデーモンが起動して居ない場合は、エラーが発生して ウィザードが終了する(データベースは、プロジェクトに追加される)。 [データベースオブジェクトの選択] ページでは、データテーブルを作成するテーブルを選択する。此処 では、テーブルのノードを開き、使用するテーブルのチェックをオンにして、[完了] ボタンをクリック する(今回は外部キーを含んで居ないシンプルなauthors テーブルを指定した)。

(26)

以上で、プロジェクト内にデータセット、データテーブル、然して、テーブルアダプタが自動的に作成 される。DB ファイル追加後のプロジェクトは、下図の様に成る。

此の時点で、プロジェクトに追加したDB ファイルは、プロジェクトファイルの有るフォルダ内にコピ ーされて居る。此の為、安心してデータベースを変更する事が出来る。

亦、DB ファイルの [出力ディレクトリにコピー] プロパティの欄が [常にコピーする] と成って居るが、 此れはVisual Basic 2010 上でプログラムを実行する度に、出力ディレクトリ(EXE ファイルが作成さ れるディレクトリ)に、DB ファイルがコピーされる事を意味して居る。

追加されたDB ファイル 自動生成されたデータセット

(27)

[データソース]ウィンドウ [データソース] ウィンドウでは、プロジェクト内に追加されて居るデータセットと其れに含まれるデー タテーブル、然して、データテーブルに含まれる列要素がツリー表示される。 [データソース] ウィンドウと謂う名前からも解る様に、此のウィンドウはプロジェクトに於いてデータ ソースと仕て使える項目を一覧して居る。此等の項目は、DataGridView コントロールや後述する BindingSource コンポーネントのデータソースと仕て使用する事が出来る。 データセットデザイナでデータテーブルの編集を行うと、[データソース] ウィンドウの内容もリアルタ イムに更新されるのが解る。 ※ DB ファイルのプロジェクトへの追加は、[新しいデータソースの追加 ]に依り行う事も出来る。此 れは、Visual Basic 2010 のメニューから [データ] - [新しいデータソースの追加] を実行する。 又は、[データソース] ウィンドウを開くと、中央に [新しいデータソースの追加] と謂うリンクが有 るので、此処をクリックしても良い。 以降は、データソース構成ウィザードが起動するので、前述の手順で設定して行く。[接続の追加] ダ イアログでは、[データベースファイル名] の部分で PUBS.MDF を指定する。

(28)

■ DataGridView コントロールの配置 [データソース] ウィンドウからテーブル(authors の項目)をフォーム上にドラッグ&ドロップすると DataGridView コントロールと幾つかのコントロールやコンポーネントが自動的にフォームに配置され る(フォーム上には、DataGridView コントロールと BindingNavigator コントロール)。 此処では、使い易い様に DataGridView コントロールの右上隅に有る小さなボタンをクリックし、 [DataGridView タスク] メニューから [親コンテナにドッキングする] を選択して、DataGridView コ ントロールをフォーム一杯に配置される様にする。

※ DataGridView コントロールのプロパティで、Dock プロパティを Fill に設定しても良い。

(29)

■ 自動作成された Windows データベースアプリケーション サンプルデータベースには、サンプルレコードが最初から何件か格納されて居るので、プログラムを実 行すると、下記の様な画面が表示される筈で有る。 [データソース] ウィンドウから項目をドラッグ&ドロップした丈だが、此のプログラムは、フォーム上 部に自動的に配置されたBindingNavigator コントロールに依り、レコードの表示、編集、追加、削除、 保存が可能なので、立派なWindows データベースアプリケーションと謂う事が出来る。

※ authors データベースでは、au_lname 列や au_fname 列のデータ型が varchar 型と仕て定義されて 居る為、此の儘では日本語のデータを扱えない。データベースエクスプローラでテーブル定義を開 き、データ型をnvarchar 型に変更すると日本語が格納出来る様に成る。亦、幾つかの列には非 Null 制約や入力形式に対する制約が設定されて居るので、其れに違反するデータを入力しようとすると 例外が発生する。何の様な制約が設定されて居るかは、データベースエクスプローラでテーブル定 義を開いて確認する事が出来る。 [データの保存] ボタンが有る事からも解る様に、此のプログラムでは、一通りデータの編集や追加、削 除が終わった処で、其の編集内容をデータベースに保存すると謂う方式が採られて居る。此れは、非接 続型データアクセスのモデルを忠実に守って居ると謂える。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 猶、フォームのName プロパティにプロジェクトと同じ名前を付けて、プログラムを実行すると、名前 空間が正しく解決されず、デザイナが自動生成するコード部分でエラーが発生する。

(30)

此の様な場合は、上記のエラー一覧で、[~が定義されて居ません] と謂う項目を、総て、クラス名の前 にGlobal. を付け加える(エラー部分の右端に表示される赤線をポイントし、▼をクリックして、エラ ー修正候補を使用すると便利)。 更に、下記の部分(Me で始まる 3 行)を、コメントアウトする。 Visual Basic ' 'TableAdapterManager ' 'Me.TableAdapterManager.authorsTableAdapter = Me.AuthorsTableAdapter 'Me.TableAdapterManager.BackupDataSetBeforeUpdate = False 'Me.TableAdapterManager.UpdateOrder = _ 'database02.PUBSDataSetTableAdapters.TableAdapterManager.UpdateOrderOption.InsertUpdateDelete 以上の修正を加えて、プログラムを実行すると、漸くアプリケーションが起動する(但し、デザイン画 面は、何故か、コントロール等が総て消えて居るが、一旦、エディタを終了して、再起動すると、復旧 して居る)。 保存した筈のデータが表示されない?! プログラムを一度終了し、再度実行すると、編集したデータは保存されて居ない。此れは、DB ファ イルの [出力ディレクトリにコピー[ プロパティが [常にコピーする] に成って居る為で有る。即 ち、[データの保存] ボタンに依り DB ファイルは更新されるが、プログラムを起動する度に其れが 編集前のDB ファイルに依り上書きされて居るからで有る。 プログラムを再実行しても前回保存した内容が残る様にするには、[出力ディレクトリにコピー] プ ロパティを [新しい場合はコピーする] に変更するか、一旦プロジェクトの [総ての保存] を行い、 其の出力ディレクトリ(bin¥Debug ディレクトリ)に DB ファイル(MDF ファイルと LDF ファイ ル)をコピーし、[出力ディレクトリにコピー] プロパティを [コピーしない] に変更してからプロ グラムを実行する。

(31)

■ 詳細項目画面の作成とカスタマイズ ■ 今回は、[データソース]ウィンドウからのドラッグ&ドロップで作成出来る下図の様なスタイルの Windows データベースアプリケーションを作成する。 以降では、[データソース] ウィンドウに PUBS データベースの authors テーブルが追加されて居る状 態を前提として居る。 ■ ドラッグ&ドロップに依る詳細項目画面の作成 上図の様なスタイルの編集画面を作る場合にも、DataGridView コントロールの場合と同様に、Visual Studio では非常に簡単で有る。 先ず、[データソース] ウィンドウで authors テーブルの項目を選択し、右端の ボタンをクリックし、 メニューから[詳細]を選択する(既定ではDataGridView が選択されて居る)。 然して、此の状態でauthors テーブル項目をフォーム上にドラッグ&ドロップする丈で有る。此れに依 りフォーム上には、authors テーブルの列の分丈、ラベルとテキストボックス(contract 列に対しては チェックボックス)が配置される。

(32)

※ DataGridView コントロールを配置した時と同様に、BindingNavigator コントロール、データセッ ト、テーブルアダプタ、BindingSource コンポーネントも自動的に追加される。 ※ 配置されるコントロールは、列のデータ型に依り、適切に選択される。上記の画面では contract 列 がBit 型で有る為、自動的にチェックボックスが配置されて居る。此の例では存在しないが、若し、 日 付 型 (DateTime 型 ) の 列 が 存 在 す れ ば 、 ド ロ ッ プ ダ ウ ン で カ レ ン ダ ー を 表 示 可 能 な DateTimePicker コントロールが配置される。 文字列や数値の行に対しては、デフォルトでは上記の画面の様にテキストボックスと仕て配置され るが、其れが編集の不要な項目で有れば、ラベルと仕て配置する事も出来る。此れにはドラッグ& ドロップする前に、[データソース]ウィンドウ上で、項目に使用されるコントロールの種類を変更 して置く。 此の状態で、F5 キーを押して実行した物が、最初の図の画面と成る。

(33)

■ 画面の編集 フォーム上で各列の名前を表示して居るラベルは単成るLabel コントロールなので、自由に編集する事 が出来る。亦、配置されたコントロールの内、不要なコントロールは削除しても良い。 但し、テーブル項目のドラッグ&ドロップに依り一度フォーム上に配置されたコントロールの種類は変 更出来ない。変更し度い場合には、其のコントロール丈をフォーム上で削除し、[データソース] ウィン ドウから、(テーブル項目ではなく)列項目を単体でフォーム上にドラッグ&ドロップする。 ■ 単純データ連結されたコントロール 此処で、[データソース] ウィンドウからドラッグ&ドロップに依り配置されたテキストボックスに、現 在のレコードの項目内容が表示される仕組みに付いて少し解説する。 此等のテキストボックスが、単にツールボックスからドラッグ&ドロップした丈のテキストボックスと 異なるのは、其のDataBindings プロパティが設定されて居る点で有る。 例えば、姓(ラストネーム)の列(au_lname 列)に対応して居るテキストボックスの DataBindings プロパティは、下図の様に、AuthorsBindingSouce - au_lname に設定されて居る。 此れは、テキストボックスのText プロパティと、自動的に追加された BindingSource コンポーネント (インスタンス名はAuthorsBindingSource)内の au_lname 列とがデータ連結して居る事を示して居 る。此の設定に依り、BindingSource コンポーネントが管理する現在のレコードから、au_lname 列に 対応したデータが自動的にテキストボックスに表示される訳で有る。 此の様な、単一レコードの特定の列(又は、特定のプロパティ)へのデータ連結は「単純データ連結」 と呼ばれる。此れに対し、DataGridView コントロールやリストボックスの様に、複数のレコードを一 度に表示出来るコントロールのデータ連結は「複合データ連結」と呼ばれる。 即ち、ドラッグ&ドロップに依り自動的に配置された総てのテキストボックスやチェックボックスは、 総て下図の様に、同じBindingSource コンポーネントに単純データ連結されて居る。

(34)

■ 単純データ連結する項目の変更 データ連結して居る列項目を変更したり、ツールボックスから配置したテキストボックスのデータ連結 を設定したり仕度い場合には、DataBindings プロパティの項目を選択して、右端のボタンをクリック する。 此れに依り、下図の様なポップアップウィンドウが出現し、連結可能なデータソースの一覧が表示され るので、此処でデータ連結する項目を選択する。 猶、テキストボックスの場合には通常、Text プロパティに対してデータ連結を行うが、基本的には、任 意のコントロールの任意のプロパティに対して、データソースと仕て指定されたオブジェクトの任意の プロパティを単純データ連結出来る。 テキストボックスで Text プロパティ以外のプロパティへデータ連結を設定する場合には、プロパティ ウィンドウのDataBindings プロパティの直ぐ下に有る (詳細) から設定を行う。 ※ 此処では説明を割愛するが、連結し度いデータソースが一覧に表示されない様な場合には、コード に依り直接 DataBindings プロパティを設定する。此のプロパティは、プロパティウィンドウ上で は、DataBindings プロパティと仕て表示される。

(35)

■ キーボードに依るレコードの移動 BindingNavigator コントロールはマウスでしか操作出来ないので、キーボード操作に依りレコードを 移動出来る様に、コードを追加する事にする(例と仕て、PageDown キーで次のレコードに進み、PageUp キーで前のレコードに戻る様にして観る)。 先ず、フォームのKeyPreview プロパティを True に設定する。此れに依りアプリケーションに対する 総てのキー入力は、一旦フォームが受け取る様に成る。次にKeyUp イベントを処理する下記の様なメ ソッド(イベントハンドラ)をフォームに追加する。 Visual Basic ' フォームで押し下げられたキーが開放された時の処理 Private Sub Form1_KeyUp(sender As System.Object, _

e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp

Select Case e.KeyCode Case Keys.PageUp Me.AuthorsBindingSource.MovePrevious() Case Keys.PageDown Me.AuthorsBindingSource.MoveNext() End Select End Sub Visual C# // フォームで押し下げられたキーが開放された時の処理

private void Form1_KeyUp(Object sender, As System.Windows.Forms.KeyEventArgs e) switch(e.KeyCode) { case Keys.PageUp: this.AuthorsBindingSource.MovePrevious(); break; case Keys.PageDown: this.AuthorsBindingSource.MoveNext(); break; } End Sub

此のメソッドでは、PageUp キー、PageDown キーが押された場合に、BindingSource コンポーネント のMovePrevious、MoveNext メソッドを呼び出して居る。此等のメソッドは BindingNavigator コン トロールの [前に戻る]、[次に移動] ボタンがクリックされた時に内部的に呼び出されて居るメソッドで 有る。

取り敢えず、此処では、2 種類のキーを処理する様に仕たが、同様の手順で Case 文を増やす事に依り、 色々なショートカットキーを追加出来る。

(36)

■ 検索ツールバーの追加 最後に、検索ツールバーを追加し、検索に該当するレコード而巳を編集出来る様にする事にする。検索 ツールバーを追加した画面は、下図の様に成る(此処では姓にing を含むレコードを検索して居る)。 此の検索ツールバー(ToolStrip コントロール)で [検索] ボタンがクリックされると、其の隣のテキス トボックスに入力された文字列を姓に含むレコード而巳がデータベースより読み込まれて編集出来る 様に成る。 此の検索機能は、検索用のクエリをテーブルアダプタに追加して置き、其れを [検索] ボタンがクリッ クされた時に呼び出すと謂う単純な仕組みだが、Visual Studio には検索ツールバーを作成する為の [検 索条件ビルダ] が用意されて居る。此処では其れを使って観る。 検索条件ビルダに依る検索ツールバーの追加 検索条件ビルダを起動するには、先ず、デザイナ画面の下に並んで居るBindingSource コンポーネント (AuthorsBindingSource)か、テーブルアダプタ(AuthorsTableAdapter)を選択し、右上の三角印 をクリックして、タスクメニューから[クエリの追加]を実行する(又は、選択後に IDE のメニュー から [データ] - [クエリの追加] を実行する)。下記の様な [検索条件ビルダ] が表示される。 ① ラベル ② テキストボックス ③ ボタン

(37)

此のダイアログ丈で、検索ツールバー(ToolStrip コントロール)の追加とテーブルアダプタへのクエ リの追加が行える。 此の画面の最初の項目で、[データソーステーブル] と表記されて居るのは、データテーブルの事で有る。 此処には、既定で、データセット(PUBSDataSet)内のデータテーブル(authors)が選択されて居る 筈で有る。 [ 新 し い ク エ リ 名 ] に は 、 テ ー ブ ル ア ダ プ タ に 追 加 す る メ ソ ッ ド 名 を 指 定 す る ( 此 処 で は FillByLastName とした)。 [クエリテキスト] には、クエリに依り実行される SQL 文を記述する(此れには [クエリビルダ] ボタ ンをクリックして、クエリビルダを実行すると便利で有る)。 ※ クエリビルダを使用すると、クエリの呼出時に実行される SQL 文を GUI に依り設計出来る。 此処では、au_lname 列の値が検索ツールバーに入力された文字列に部分一致する様なレコードを取得 し度いので、au_lname 列のフィルタのセルに、下記のコードを入力する。 LIKE '%' + @lname + '%' ※ @lname の部分は外部から値を指定する為の名前付きパラメータで有る。パラメータ名は何でも構わ ない。亦、%は、0 文字以上の文字と一致する SQL Server でのワイルドカード文字で有る。 猶、Access データベース(MDB ファイル)では、名前付きパラメータを使用する事は出来ないの で、代わりに、プレースホルダ( ? )を使用する。例えば、上記は、下記の様に記述する。 LIKE '%' + ? + '%'

例えば、ing で検索された場合には、此の LIKE 文は最終的に LIKE '%ing%' と成り、au_lname 列 にing を含む Gringlesby や Stringer のレコードが編集出来る様に成る。

(38)

クエリビルダと検索条件ビルダを [OK] ボタンをクリックして閉じると、フォームは下図の様な画面に 成る。後は、検索ツールバー上のラベルとボタンのテキスト等のプロパティを適当に変更すれば、完成 で有る。 ※ クエリビルダで [クエリの実行] ボタンをクリックすると、クエリの実行結果を確認する事が出来、 亦、検索条件ビルダでは、生成されたクエリ文を観る事が出来る。 検索条件ビルダの設定が完了すると自動的に検索ツールバーがフォームに配置される。此処では1 個而 巳だが、ツールバー内のテキストボックスはクエリ内の名前付きパラメータの数に応じて追加される。

コード画面を観ると、ToolStripButton コントロール(FillByLastNameToolStripButton)の Click イ ベントには、下記の様なコードが追加されて居る。

Visual Basic

Private Sub FillByLastNameToolStripButton_Click(sender As System.Object, _ e As System.EventArgs) Handles FillByLastNameToolStripButton.Click Try Me.AuthorsTableAdapter.FillByLastName(Me.PUBSDataSet.authors, _ LnameToolStripTextBox.Text) Catch ex As System.Exception System.Windows.Forms.MessageBox.Show(ex.Message) End Try End Sub 此のコードに依り、データセットの内容は検索に一致したレコード而巳と成る。FillByLastName メソ ッ ド の 中 身 は 、 デ ー タ セ ッ ト の コ ー ド ビ ハ イ ン ド フ ァ イ ル ( デ フ ォ ル ト で は フ ァ イ ル 名 は PUBSDataSet.Designer.vb」を観る事が出来る。

参照

関連したドキュメント

Amortized efficiency of list update and paging rules.. On the

SUSE® Linux Enterprise Server 15 for AMD64 & Intel64 15S SLES SUSE® Linux Enterprise Server 12 for AMD64 & Intel64 12S. VMware vSphere® 7

ESET Server Security for Windows Server、ESET Mail/File/Gateway Security for Linux は

The performance measures- the throughput, the type A and type B message loss probabilities, the idle probability of the server, the fraction of time the server is busy with type r,

Another new aspect of our proof lies in Section 9, where a certain uniform integrability is used to prove convergence of normalized cost functions associated with the sequence

mkdocs serve - Start the live-reloading docs server.. mkdocs build - Build the

・Microsoft® SQL Server® 2019 Client Access License (10 User)ライセンス証書 オープン価格. オープン価格 Microsoft SQL

・M.2 Flash モジュール専用RAID設定サービス[PYBAS1SM2]とWindows Server 2022 Standard(16コア/Hyper-V)[PYBWPS5H]インストール/Windows Server 2019