Grow up

生活とプログラミング

C#から踏み台サーバを経由してSQL Serverに接続する

はじめに

複数人による開発でSQL Serverに接続できないかと考えました。
単純にEC2のポートを開けると不正にログインを試みるbotに耐えられずSQL Server が停止しまうため、踏み台サーバを経由した接続を行うことにしました。

全体像

A : 踏み台サーバ
B : データベースサーバ
f:id:knkomko:20210325072334p:plain

A : 踏み台サーバ

SSH接続をする22番ポートを開けています。
またSSH接続用アカウントを新規作成しています。
f:id:knkomko:20210326042123p:plain

今回はSSH.NETを使用してポートフォワーディングを行うため、踏み台サーバではポートフォワーディングの設定は行っていません。
f:id:knkomko:20210324014425p:plain

B : データベースサーバ

SQL Serverの規定インスタンスに接続する1433番ポートを開けています。

ソースコード

C#からSSH接続が行えるSSH.NETを使用しました。
github.com

ソースコードはこちらです。
github.com

SSH.NETでは秘密鍵も利用可能です。

// 踏み台サーバのホスト名
string bastionServer = "XXXXXXXXXX";
// 踏み台サーバのアカウント名
string userName = "XXXXXXXXXX";
// 踏み台サーバのパスワード
string password = "XXXXXXXXXX";

ConnectionInfo info = new ConnectionInfo(bastionServer, 22, userName,
    new AuthenticationMethod[] {
         new PasswordAuthenticationMethod(userName, password)
    }
);

ForwardedPortLocal からポートフォワーディングを行っています。

// SQL Server 接続文字列
string connectionString = @"Data Source=127.0.0.1;Integrated Security=False;User ID=XXXXXXXXXX;Password=XXXXXXXXXX";
// データベースサーバのホスト名
string dbServer = "XXXXXXXXXX";

using (var client = new SshClient(info))
{
    client.Connect();
    var forward = new ForwardedPortLocal("127.0.0.1", 1433, dbServer, 1433);
    client.AddForwardedPort(forward);
    forward.Start();
    using (var connection = new SqlConnection(connectionString))
    {
        using (var command = connection.CreateCommand())
        {
            try
            {
                connection.Open();

                connection.Open();

                command.CommandText = @"SELECT count(*) AS count FROM employee";
結果

踏み台サーバを経由してSQL Server に接続する事ができました。
f:id:knkomko:20210326040108p:plain

スマホにある子供の写真を親のLINEへ定期的に送ってみた

f:id:knkomko:20210321123702p:plain

はじめに

コロナの影響で実家に帰れない為、子供の写真を親のLINEへ送っています。
しかし段々とLINEから送る事を手間に感じてしまい、送り忘れも増えました。

画像共有アプリの利用も考えましたが、アプリのインストール方法から親に説明する必要があるため、新しいアプリの利用は現実的な方法ではありません。

そこで写真を撮るだけで親のLINEに送れないかと考え、取り組むことにしました。
また無料で使えるサービスを組み合わせて実現することを目標にしました。

料金

LINEに1日1枚の画像を送る程度であれば無料の範囲で実現できました。

容量15GBまで無料で使えます。
Google のストレージを追加購入する - パソコン - Google ドライブ ヘルプ

APIも無料で使えます。
Google Drive Apis の利用に関して

  • LINE Messaging API

フリープランを使用していて無料です。
f:id:knkomko:20210321202737p:plain
料金プラン|LINE for Business

サービス間の連携

f:id:knkomko:20210321154153p:plain

①画像を読み込む
子供の写真を撮影するスマホGoogleフォトのアプリをインストールしています。
同期の設定によりスマホ内の写真はGoogleフォトのクラウドストレージに自動でバックアップされるので、Google Apps Scriptでその画像を毎朝9時に読み込みます。

②画像をコピー

Googleアカウントを持たない人にも共有する一般公開のフォルダにGoogleフォトの画像をコピーします。
一般公開とすることでLINEに画像の表示を可能にしています。

③メッセージの送信
Googleフォトにコピーした画像のURLをLINEに送信します。
画像のURLは外部から閲覧できるよう部分的に変更をしています。

④画像の表示
LINEを開くとGoogleドライブに保存していた画像が表示されます。

学び

Googleドライブ
LINEに画像を表示するにはドライブのURLを変更する必要がありました。
ドライブのURLから画像にアクセスできるURLに変更しています。

var downloadURL = buff.getUrl().replace("/file/d/", "/uc?id=").replace("/view?usp=drivesdk", "")

【変更前】
https://drive.google.com/file/d/<ファイルID>/view?usp
【変更後】
https://drive.google.com/uc?id=<ファイルID>

②ダウンロードリンク
画像のURLに "=d" を付加すると画像のダウンロードリンクになります。
LINEで送った画像のダウンロードを可能にする為に必要でした。
f:id:knkomko:20210321193336p:plain

③LINE Messaging API
画像を送るには imageThumbnail と imageFullSize を使用します。
変数downloadURLにGoogleドライブの画像のURLを格納しています。

      var token = ["XXXXXXXXXXXXXXXX"]; //LINEで自動通知をする宛先のトークン。
      var options =
      {
        "method"  : "post",
        "payload" : {"message": "Today's photo.",
                      "imageThumbnail" : downloadURL,
                      "imageFullsize"  : downloadURL,
                    }, 
        "headers" : {"Authorization" : "Bearer "+ token}
      };
    
      UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options); 
結果

僕自身はLINEを使う事が無くなり写真を撮るだけで良くなりました。
なにより我が子の成長を母と兄に見てもらえて嬉しく思っています。

f:id:knkomko:20210321125528p:plain:w350

Run MVP sample app on the Android emulator

f:id:knkomko:20201230045042p:plain

はじめに

2021年1月にAndroidアプリを開発する予定ができました。
何も知らない状態から20日で何が開発できるのか見当もつきませんが
まずはMVPアーキテクチャを学ぶことにしました。

MVPを選択した理由はMVCと似ていて分かりやすかったためです。
eh-career.com

MVPのサンプルをエミュレータで実行しようとしたのですが
一筋縄にはいかなかったため実行にあたり操作した内容をまとめます。

Download MVP sample app

リポジトリからソースコードをダウンロードします。
github.com

SDK

architecture-sample の targetSdkVersion を確認します。
f:id:knkomko:20201230035457p:plain

必要に応じてSDKをインストールします。
f:id:knkomko:20201230035726p:plain

Android emulator

バーチャルデバイスを追加します。
f:id:knkomko:20201230040047p:plain

適当なものを選択します。
f:id:knkomko:20201230040452p:plain

SDKに対応したシステムイメージをダウンロードします。
f:id:knkomko:20201230040520p:plain

ダウンロード後は順に進んで完了です。
f:id:knkomko:20201230040725p:plain

Android emulator HYPERVISOR_ERROR

エミュレータを実行すると HYPERVISOR_ERROR が発生する場合の対策です。
f:id:knkomko:20201230041244p:plain

詳細な内容は以下を参照してください。
qiita.com

Qiitaを参考に私が実際に操作した内容になります。
プログラムと機能の削除 -> Windwosの機能の有効化または無効化
f:id:knkomko:20201230040902p:plain

Hyper-VWindowsハイパーバイザープラットフォーム のチェックを外します。
[OK]ボタンを押した後、変更を適用させるためにWindowsを必ず再起動します。
f:id:knkomko:20201230041051p:plain

Android Studio を起動するとエミュレータの設定画面が表示されました。
メモリサイズは規定値の4GBを選択して次へ進みました。
f:id:knkomko:20201230043822p:plain

インストール後のログにエラーが無いことを確認して完了です。
f:id:knkomko:20201230044129p:plain

Encryption unsuccessful

エミュレータを実行すると Encryption unsuccessful になる場合の対策です。
f:id:knkomko:20201230042459p:plain

tratail の回答が参考になりました。
teratail.com

使用するエミュレータで Wipe Data を実行します。
f:id:knkomko:20201230042914p:plain

Run MVP sample app

MVPのサンプルを実行することが出来ました。
f:id:knkomko:20201230044337p:plain:w300

EC2 Ubuntu に Windows Subsystem for Linux (WSL1) からSSH接続する

f:id:knkomko:20201221012630p:plain

はじめに

年末年始の休みを活用して改めてサーバ構築の勉強をしたいと思い
UbuntuWindows から SSH 接続できるようにしたので書き残します。

Ubuntu は EC2 に作成をしました。

SSH接続

調べてみると Windows から SSH 接続は簡単に出来るようです。

・Traterm
eng-entrance.com

SSHクライアント
dev.classmethod.jp

Windows Subsystem for Linux
www.atmarkit.co.jp

今回は WindowsUbuntu が使える機能 Windows Subsystem for Linux (WSL1) をインストールして SSH 接続に使用することにしました。
WSLがあれば毎回 SSH 接続をしなくてもローカルでコマンドの確認が行えます。

Ubuntu EC2 インスタンスの作成

キーペアの作成までこちらのサイトが参考になりました。
www.acrovision.jp

Windows Subsystem for Linux インストール

インストール手順についてはこちらの記事が分かりやすかったです。
qiita.com

Ubuntu EC2 インスタンス SSH 接続

WSL から ssh コマンドを使用する事で接続が可能でした。

ssh -i {秘密鍵}.pem ubuntu@{インスタンスのIPv4パブリックIP}

pemはEC2インスタンス作成時にダウンロードしたキーペアを指定します。

原因は分からなかったのですが接続の確立が出来ないというメッセージ後に
再試行を許可することで SSH 接続が成功しました。

f:id:knkomko:20201221010907p:plain

Setup DB First EntityFrameworkCore SQL Server

f:id:knkomko:20201220181736p:plain

はじめに

.Net Core で EntityFramework を使う際に .NET Standard と違って試行錯誤したのでDBファーストで使用した手順をまとめます。

対象のフレームワーク

今回は.NET Core 3.1を使用しました。
f:id:knkomko:20201220173109p:plain

開発者用 PowerShell

コマンドは全て開発者用PowerShellから実行します。

カレントディレクトリはプロジェクトルートです。

PS C:\develop\WebApplication1\WebApplication1> dir


    ディレクトリ: C:\develop\WebApplication1\WebApplication1


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/12/20     17:30                bin
d-----       2020/12/20     17:30                obj
d-----       2020/12/20     17:29                Properties
-a----       2020/12/20     17:29            162 appsettings.Development.json
-a----       2020/12/20     17:29            192 appsettings.json
-a----       2020/12/20     17:30            723 Program.cs
-a----       2020/12/20     17:30           1295 Startup.cs
-a----       2020/12/20     17:29            148 WebApplication1.csproj
dotnet ef ツールのインストール

.NET Core 3.0 以降は .NET SDKdotnet ef ツールが含まれていないため
初めて使用する場合はインストールが必要です。

dotnet tool update --global dotnet-ef
Microsoft.EntityFrameworkCore.Design の追加

スキャフォールディングに必要な Design パッケージを追加します。

dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer の追加

スキャフォールディングに必要なデータベースプロバイダーを追加します。

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Models フォルダの作成

コードを保存する Models フォルダを作成します。
f:id:knkomko:20201220180522p:plain

スキャフォールディング

データベースから DBContext と Entity のコードを Models フォルダに作成します。

dotnet ef dbcontext scaffold "Server=[ホスト名];Database=[データベース名];persist security info=True;user id=[ユーザーID];password=[パスワード];MultipleActiveResultSets=True" Microsoft.EntityFrameworkCore.SqlServer -o Models
確認

EntityFrameworkCoreを使用してデータベースからコードが作成できました。

f:id:knkomko:20201220180806p:plain

参考資料

docs.microsoft.com

Setup DB First EntityFramework SQLite

f:id:knkomko:20201114012601p:plain


ソリューションファイルの作成

サンプルとして Windows Form アプリケーションを作成しました。
f:id:knkomko:20201113222821p:plain:w300

1. SQLite Compact Toolbox のインストール

拡張機能の管理から SQLite/SQL Server Compact Toolbox をインストールします。
f:id:knkomko:20201113223609p:plain

2. GAC に SQLite をインストール

sqlite-netFx46-setup-bundle-x86-2015-1.0.113.0.exe をダウンロードします。
デザイナコンポーネントは64bit版には含まれていないため32bit版を使用します。
f:id:knkomko:20201113230709p:plain

GACにインストール、デザイナコンポーネントのインストールを選択します。
f:id:knkomko:20201113230318p:plain

ちなみに64bit版のSetupだとデザイナーコンポーネントの選択がありません。
f:id:knkomko:20201113231439p:plain

GACに登録されている事をToolboxから確認します。
f:id:knkomko:20201113232257p:plain

3. System.Data.SQLite NuGet パッケージのインストール

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.configの
DbProviderFactories タグからバージョン番号を確認します。
f:id:knkomko:20201113234335p:plain

上記で確認したバージョン番号と同じ NuGet パッケージをインストールします。
NuGet Gallery | System.Data.SQLite 1.0.113.6
f:id:knkomko:20201113235317p:plain

インストール後の packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="EntityFramework" version="6.3.0" targetFramework="net48" />
  <package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.113.3" targetFramework="net48" />
  <package id="System.Data.SQLite" version="1.0.113.0" targetFramework="net48" />
  <package id="System.Data.SQLite.Core" version="1.0.113.6" targetFramework="net48" />
  <package id="System.Data.SQLite.EF6" version="1.0.113.0" targetFramework="net48" />
  <package id="System.Data.SQLite.Linq" version="1.0.113.0" targetFramework="net48" />
</packages>

インストール後の App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
  </startup>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite.EF6" />
      <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
    <remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
  </system.data>
</configuration>

今回のApp.configには設定が不足している為 providers タグに設定を追加します。
f:id:knkomko:20201114002938p:plain

変更後の App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
  </startup>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
      <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite.EF6" />
      <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
    <remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
  </system.data>
<connectionStrings><add name="EmployeeDBContext" connectionString="data source=C:\Users\q612.TOHNICHI\source\repos\SQLiteEFSample\Employee.db" providerName="System.Data.SQLite.EF6" /></connectionStrings></configuration>
4. DBファーストの使用

DBファースト用に department テーブルを作成します。
f:id:knkomko:20201114000757p:plain

DBの作成には DB Browser for SQLite を使用しました。
Downloads - DB Browser for SQLite

ADO.NET Entity Data Model を作成します。
f:id:knkomko:20201114001047p:plain

データベースから Code First を選択します。
f:id:knkomko:20201114001148p:plain

SQLite Provider (Simple for EF6 by ErikEJ) を使用します。
f:id:knkomko:20201114001615p:plain

Data Source にDBのファイルパスを指定します。
f:id:knkomko:20201114001730p:plain

テーブルを指定します。
f:id:knkomko:20201114001824p:plain

Department と DBContext が作成されました。
f:id:knkomko:20201114005254p:plain

全件検索した結果を一覧表示します。

using System;
using System.Linq;
using System.Windows.Forms;

namespace SQLiteEFSample
{
    using Model;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            using (EmployeeDBContext context = new EmployeeDBContext())
            {
                DataGridView.DataSource = context.Department.AsNoTracking().ToList();
            }
        }
    }
}

無事 department テーブルの一覧を表示する事ができました。
[f:id:knkomko:20201114005346p:plain:300]

補足 App.config の修正を行わなかった場合の動作

不足していた System.Data.SQLite を追加せず実行した場合の動作です。

      <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />

SQLの発行を行う際に InvalidOperationException が発生します。

System.InvalidOperationException: 'No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SQLite'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.'

f:id:knkomko:20201114002230p:plain

Setup DB First JetEntityFrameworkProvider in VS2019

f:id:knkomko:20201025011901p:plain

準備① JetEntityFrameworkProvider

GitHubからソースコードをダウンロードします。
f:id:knkomko:20201022004851p:plain

準備② レジストリのバックアップ

今回は VisualStudio のレジストリをエクスポートしました。
必要に応じて他のレジストリもエクスポートしておくと安心です。

regedit を実行。
f:id:knkomko:20201022005849p:plain

VisualStudio を選択。
コンピューター\HKEY_CURRENT_USER\Software\Microsoft\VisualStudio
f:id:knkomko:20201022010036p:plain

エクスポートで保存。
f:id:knkomko:20201022010202p:plain

準備③ レジストリキー作成

レジストリエディタからVisualStudioにキーを新規作成します。
コンピューター\HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\
f:id:knkomko:20201022011432p:plain

自由に名前を付けて良いのですが今回は OMGITWORKS で作成。
f:id:knkomko:20201022011629p:plain

1. Visual Studio を管理者として実行

f:id:knkomko:20201022005712p:plain

GitHubからダウンロードした JetEntityFrameworkProvider を開く。
f:id:knkomko:20201022010426p:plain

2. install.cmd 編集

JetDdexProvider の install.cmd を開く。
f:id:knkomko:20201022010741p:plain

REGROOT のキーをレジストリエディタで作成した OMGITWORKS に変更。
f:id:knkomko:20201022011112p:plain

3. プロジェクトのコンパイル

コンパイルするためにビルドイベントの内容を編集します。
使用しているVisualStudioのバージョンによってパスが変わるため
環境に合わせてパスを変えて、コンパイルできるようにします。

3-1. JetDdexProvider ビルドイベント編集

JetDdexProvider のプロパティからビルドイベントを編集。
f:id:knkomko:20201022013407p:plain

① ビルド前イベントのコマンドライン

call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars32.bat"
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\gacutil.exe" /u JetEntityFrameworkProvider.dll

赤下線はVisualStudioのバージョンごとに変わるので確認して変更します。
f:id:knkomko:20201022012952p:plain

② ビルド後イベントのコマンドライン

"$(ProjectDir)Install.cmd" /ranu /codebase "$(TargetDir)$(TargetFileName)"

call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars32.bat"

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\gacutil.exe" /i "$(TargetDir)JetEntityFrameworkProvider.dll" /f

赤下線はVisualStudioのバージョンごとに変わるので確認して変更します。
f:id:knkomko:20201022013250p:plain

3-3. JetEntityFrameworkProvider ビルドイベント編集

JetEntityFrameworkProvider のプロパティからビルドイベントを編集。
f:id:knkomko:20201022013536p:plain

① ビルド前イベントのコマンドライン

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\gacutil.exe" /u "$(TargetName)"

赤下線はVisualStudioのバージョンごとに変わるので確認して変更します。
f:id:knkomko:20201022013643p:plain

② ビルド後イベントのコマンドライン

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\gacutil.exe" /if "$(TargetPath)"

赤下線はVisualStudioのバージョンごとに変わるのでパスを確認して変更します。
f:id:knkomko:20201022013829p:plain

3-4. JetDdexProvider, JetEntityFrameworkProvider リビルド

JetDdexProvider
f:id:knkomko:20201022014247p:plain

JetEntityFrameworkProvider
f:id:knkomko:20201022014320p:plain

正常終了し、出力にエラーメッセージが無ければ成功です。
f:id:knkomko:20201022014458p:plain

レジストリエディタからDataProviders, DataSourcesが作成されている事を確認します。
コンピューター\HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\OMGITWORKS
f:id:knkomko:20201022022629p:plain

3-5. VisualStudio2019 プライベートハイブ読み込み

レジストリでは、各種の情報がキー、サブキー、値と階層的に管理されている。
ハイブは、ハードウェア設定やソフトウェア設定、セキュリティ設定など、レジストリに保存される情報のうち、特定分野に関する一連の情報を識別するセクションを意味する。

Insider's Computer Dictionary:ハイブ とは? - @IT

プライベートハイブの編集方法については以下の記事が参考になりました。

Fortunately, you can use regedit.exe to load a private hive. You need to select the HKEY_USERS node, and click the File > Load Hive… menu. You select the privateregistry.bin file, give a name to the hive (I entered “VS2017PrivateRegistry”) and now you can see the 15.0_Config key populated as usual (note: use File > Unload Hive when done):

Some implications of the new modular setup of Visual Studio 2017 for VSX developers | Visual Studio Extensibility (VSX)

VisualStudioのレジストリにJetEntityFrameworkProviderを登録するのですが、2017からプライベートハイブに変わってしまいコンパイルだけで登録出来ないため、手作業で行います。

まずはVisualStudioのレジストリ(プライベートハイブ)を確認。
~\AppData\Local\Microsoft\VisualStudio\
f:id:knkomko:20201022015345p:plain

プライベートハイブのフォルダ名 16.0 はVisualStudioのバージョンです。
利用している開発環境のバージョンと一致するフォルダを探してください。
f:id:knkomko:20201022015514p:plain

プライベートハイブを編集する前に起動しているVisualStudioを全て終了します。
起動していると以下の警告メッセージが表示されて編集ができません。
f:id:knkomko:20201024214059p:plain

レジストリエディタにて HKEY_USER を選択。
f:id:knkomko:20201022021236p:plain

レジストリエディタのハイブの読み込みから privateregistry.bin を指定。
f:id:knkomko:20201022021429p:plain

キー名を付ける必要があるので分かりやすい名前を付けます。
f:id:knkomko:20201024220140p:plain

これによりVisualStudioのプライベートハイブが編集できるようになります。
f:id:knkomko:20201024220257p:plain

3-6. レジストリ DataProviders, DataSources エクスポート

DataProviders, DataSoures それぞれエクスポートします。
f:id:knkomko:20201024214647p:plain

ドキュメントフォルダにregというフォルダを作成してエクスポートしました。
f:id:knkomko:20201024214745p:plain

3-7. レジストリ DataProviders, DataSources 編集

エクスポートした DataProviders, DataSources を編集します。
間違えても良いように _new としてコピーしたものを編集します。
f:id:knkomko:20201024215153p:plain

regファイルを右クリックして、今回はメモ帳で編集しました。
f:id:knkomko:20201024220910p:plain

OMGITWORKSのパスを全て、プライベートハイブのパスに変更します。
・変更前
f:id:knkomko:20201024221110p:plain
・変更後
f:id:knkomko:20201024221421p:plain

3-8. レジストリ DataProviders, DataSources インポート

パスをプライベートハイブに変更した DataProviders, DataSources をレジストリエディタでインポートします。DataProviders, DataSourcesがある_Config が付くレジストリキーにインポートします。
f:id:knkomko:20201024222001p:plain

DataProviders を選択します。
f:id:knkomko:20201024225329p:plain

インポートから先ほど編集した DataProviders_new.reg を開きます。
f:id:knkomko:20201024225415p:plain

完了するとDataProvidersにJetDDEXProviderが追加されます。
f:id:knkomko:20201024225659p:plain

DataProviders と同様に DataSources もインポートします。

3-9. VisualStudio2019 プライベートハイブアンロード

読み込んでいたプライベートハイブを選択します。
f:id:knkomko:20201024223203p:plain

アンロードを左クリック。
f:id:knkomko:20201024223311p:plain

警告メッセージが表示されます。
f:id:knkomko:20201024223338p:plain

はいボタンを押してレジストリキーのアンロードを実行します。
f:id:knkomko:20201024223358p:plain

4. machine.config に JetEntityFrameworkProvider 追加

machine.config をデスクトップにコピーして編集をします。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
f:id:knkomko:20201024223906p:plain

DbProviderFactories に JetEntityFrameworkProvider を追加します。
f:id:knkomko:20201024224319p:plain

元の場所にmachine.configを上書きをします。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config

DB First 確認

Accessでデータベースを作成します。
f:id:knkomko:20201024232924p:plain

NuGet から JetEntityFrameworkProvider をインストールします。
f:id:knkomko:20201024230343p:plain

ADO.NET Entity Data Model からDbContextの名称を入力して追加します。
f:id:knkomko:20201024233348p:plain

データベースから Code First を選択して次へ。
f:id:knkomko:20201024224654p:plain

新しい接続を左クリックします。
f:id:knkomko:20201024233433p:plain

データソースを変更します。
f:id:knkomko:20201024233531p:plain

<その他>からJet DDEX provider for JetEntityFrameworkProviderを選択します。
f:id:knkomko:20201024233649p:plain

DataSource と Provider を入力します。
f:id:knkomko:20201024233846p:plain

接続文字列が作成されます。
f:id:knkomko:20201024234031p:plain

モデルを作成するテーブルを選択します。
f:id:knkomko:20201024234106p:plain

Employee、SampleContext が作成できました。
f:id:knkomko:20201024234231p:plain