endokのブログ

IT・プログラミングネタ

ITカンファレンス個人的まとめ2018

2018年は時間を作って参加や視聴したいと思うので、開催時期などまとめてみる。
(2018/01/03時点情報)
企業やユーザーグループが主催している大きめのもので、自分が行こうかなと思っているもの中心。
偏りあると思うので、追加等あればコメントください。
また、日本の技術系カンファレンスまとめ - Qiitaの記事も参考にさせていただきました。

国内

企業主催

AWS Summit Tokyo

http://www.awssummit.tokyo/
AWSの開発者向けイベント。
2018年の日程は未発表。去年は5月末に開催。

Microsoft de:code

https://www.microsoft.com/ja-jp/events/decode/2018
Microsoftの開発者向けイベント。
2018年は5/22-5/23開催。

Microsoft Tech Summit

https://www.microsoft.com/ja-jp/events/techsummit/
Microsoftの企業や組織のIT技術者向けイベント。
2018年の日程は未発表。去年は11月に開催。

楽天テクノロジーカンファレンス

https://tech.rakuten.co.jp/
楽天の技術イベント。
2018年の日程は未発表。去年は10月末に開催。

Cookpad TechConf

https://techconf.cookpad.com
Cookpadの技術イベント。
2018年は2/10開催。

NTT Tech Conference

https://ntt-developers.github.io/ntt-tech-conference/
NTTグループの技術イベント。
2018年の日程は未発表(不定期?)。去年は1月と8月に開催。

全般

オープンソースカンファレンス

https://www.ospn.jp/
オープンソースがテーマのイベント。
日本各地で開催されている。
2018年の東京は2/23-2/24で開催。

Developers Summit

http://event.shoeisha.jp/devsumi
「技術者コミュニティとの連携から生まれた総合ITコンファレンス」とのこと。
同僚で行く人が多い。
2018年は2/15-2/16で開催。

CEDEC

http://cedec.cesa.or.jp/
コンピュータエンターテインメント関連の技術者向けイベント。
個人的にゲーム好きなので行ってみたい。けど個人で行くにはちょっと高いかな。
2018年は8/22-8/24で開催。

iOS

iOSDC Japan

https://iosdc.jp/
iOS開発者向けイベント。
2018年の日程は未発表。去年は9月に開催。

try!Swift

https://www.tryswift.co/events/2018/tokyo/en/
Swift開発者向けイベント。
2018年は3/1-3/2開催。

Android

Android ABC

http://abc.android-group.jp/
Android Bazaar and Conference。
2018年は2/3開催。秋/冬にも開催する年がある。

Droid Kaigi

https://droidkaigi.jp/
Androidカンファレンス。
2018年は2/8-2/9開催。

フロントエンド

FRONTEND CONFERENCE

http://kfug.jp/
関西のフロントエンド技術者向けイベント。
2018年の日程は未発表。去年は3月開催。

HTML5 Conference

http://events.html5j.org
Web技術者向けイベント。
2018年の日程は未発表。去年は9月開催。

Java

JJUG CCC

http://www.java-users.jp
Java技術者向けイベント。
SpringとFallの年2回開催。
2018年の日程は未発表。去年は5月と11月開催。

Scala

ScalaMatsuri

http://2018.scalamatsuri.org/
Scala技術者向けイベント。
2018年は3/16-3/18開催。

Ruby

RubyKaigi

http://rubykaigi.org/
Ruby技術者向けイベント。
2018年は5/31-6/2開催。

海外

企業主催

F8 Facebook Developer Conference

https://www.f8.com/
Facebookの開発者向けイベント。
2018年は5/1-5/2開催。

Microsoft Build

https://build.microsoft.com/
Microsoftの開発者向けイベント。
2018年の日程は未発表。去年は5月に開催。

Google I/O

https://events.google.com/io/
Googleの開発者向けイベント。
2018年は5/16という情報ありだが未確定?

Apple WWDC

https://developer.apple.com/wwdc/
Appleの開発者向けイベント。
2018年の日程は未発表。去年は6月に開催。

AWS re:Invent

https://reinvent.awsevents.com/
AmazonAWS開発者向けイベント。
2018年は11/26-11/30開催。

.NETの各種DBアクセス方法を試す(DataSet,EntityFramework,Dapperなど)

はじめに

.NET使って何か作ろうと思ったのだが、仕事では独自Frameworkばかり使っていて標準的な方法を触ったことがないので、有名所のDBアクセス方法を試してみたいと思う。

サンプルコードの全体は下記。
GitHub - endok/sample-dotnetdb: .NETのDBアクセスサンプルコード。

対象

試す対象は、

環境

データ準備

下記状態を前提とする。

下記テーブル、データを作成しておく。

CREATE TABLE member
(
	id int PRIMARY KEY,
	name nvarchar(20) NOT NULL,
	age int NOT NULL
)

INSERT INTO member (id, name, age) VALUES (1, 'Alice', 20)
INSERT INTO member (id, name, age) VALUES (2, 'Bob', 25)
INSERT INTO member (id, name, age) VALUES (3, 'Carol', 30)

このような状態になる。
f:id:endok:20171230161433p:plain

ADO.NET SqlClient

たぶん一番シンプルにADO.NETを使うパターン。
System.Data.SqlClientあたりをusingするだけで使える。
SQLServerに接続するためのクライアントで、ODBCだったりOracleの場合は別のクラスを利用する。

今回は、DataReaderでの参照、UPDATE文の発行を試した。
DataReaderは、前方参照専用、読み取り専用だがパフォーマンスに優れるとのこと。

サンプルコード

        private static void SqlCommandSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // SqlCommandによる参照
                string selectquery = "SELECT id, name, age FROM member WHERE age >= @age ";

                SqlCommand selectcommand = new SqlCommand(selectquery, connection);
                selectcommand.Parameters.AddWithValue("@age", 25);

                SqlDataReader reader = selectcommand.ExecuteReader();
                while (reader.Read())
                {
                    Console.WriteLine("id={0},name={1},age={2}", reader[0], reader[1], reader[2]);
                }
                reader.Close();

                // SqlCommandによる更新
                string updatequery = "UPDATE member SET age = 40 WHERE id = @id";

                SqlCommand updatecommand = new SqlCommand(updatequery, connection);
                updatecommand.Parameters.AddWithValue("@id", 3);

                updatecommand.ExecuteNonQuery();
            }
        }

ADO.NET DataSet

こちらもADO.NET標準の仕組み。
データソースに依存せず、メモリ上でリレーショナルデータを扱うための仕組み。DBなど既存のデータソースとのやり取りにはDataAdapterを介する。
テーブルなど一つのデータのまとまり単位でDataAdapterを定義して、CRUD操作するSQLを設定。その後はDataSetを操作した結果をDBに同期するという使い方となる模様。

今回はDataSetでの参照、データ更新を試した。

データソースに依存しないで操作できること、細かいことを考えずにデータ取得、同期できるという良さがある。しかしDataAdapterの定義がやや面倒そうという印象。

サンプルコード

        private static void DataSetSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // DataSetによる参照、更新
                string selectQuery = "SELECT id, name, age FROM member";
                string updateQuery = "UPDATE member SET age = @age WHERE id = @id";

                SqlDataAdapter adapter = new SqlDataAdapter();

                // 主キー情報をDBから取得
                adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;

                // クエリの設定
                adapter.SelectCommand = new SqlCommand(selectQuery, connection);
                adapter.UpdateCommand = new SqlCommand(updateQuery, connection);

                // Updateパラメータの設定
                SqlParameter ageParam = new SqlParameter();
                ageParam.ParameterName = "@age";
                ageParam.SourceColumn = "age";
                adapter.UpdateCommand.Parameters.Add(ageParam);
                SqlParameter idParam = new SqlParameter();
                idParam.ParameterName = "@id";
                idParam.SourceColumn = "id";
                adapter.UpdateCommand.Parameters.Add(idParam);

                DataSet dataset = new DataSet();
                adapter.Fill(dataset, "memberTable");
                DataTable datatable = dataset.Tables["memberTable"];

                // データの参照
                foreach (DataRow row in datatable.Rows)
                {
                    Console.WriteLine("id={0},name={1},age={2}", row["id"], row["name"], row["age"]);
                }

                // データの更新
                DataRow carolRow = datatable.Rows.Find(3);
                carolRow["age"] = 50;

                adapter.Update(dataset, "memberTable");
            }

        }

EntityFramework

ADO.NETに含まれるデータアクセスフレームワーク。いわゆるORMで、データソースとオブジェクトをマッピングして取り扱う。
DBマイグレーションの仕組みも備えている。

VisualStudio2012以上でないとEntityFrameworkToolsが利用できない。

導入方法

NuGetでインストールする。
プロジェクトを右クリックして[NuGetパッケージの管理...]の参照で"EntityFramework"を検索してインストールする。
※Dapperも同じプロジェクトに導入する場合、v6.1.3をインストールする。

EntityFrameworkのワークフロー

Entity Framework (EF) Documentation の概要

EntityFramewokでは概念モデルを作成するにあたり、「コードファースト」「モデルファースト」「データベースファースト」という方式がある。

コードファースト・・・ソースコード上にModelクラスをまず作成。その情報を元にDBスキーマを作成するという方式。スキーマの変更は、マイグレーション機能で管理する。
モデルファースト・・・EFデザイナを利用してVisualStudio上でモデルを追加。その情報をDBスキーマに反映するという方式。
データベースファースト・・・DBスキーマSQLでまず作成。その情報をVisualStudioのモデル(ソースコード、EFデザイナ)に反映するという方式。

今回はDBスキーマ作成済のため、データベースファースト方式を試す。

モデルのリバースエンジニアリング

プロジェクトを右クリックして[追加]→[新しい項目]でデータカテゴリの"ADO.NET Entity Data Model"を追加する。
f:id:endok:20180101120234p:plain

"データベースからEF Desginger"を選ぶ。
f:id:endok:20180101021221p:plain

データ接続を選択し、App.Configに保存する。
f:id:endok:20180101120342p:plain

接続の設定は適当なものを選ぶまたは新規作成する。
対象のデータベースオブジェクト(今回はmemberテーブル)を選択する。
f:id:endok:20180101120452p:plain

下記のようにDBの情報をもとに抽出されたモデル情報がデザイナに表示される。
f:id:endok:20180101115134p:plain

クエリの方式

いくつか方法があるが、基本的にはLINQtoEntitiesでアクセスするのが主流の模様。複雑なクエリを発行する際には、EntitySQLというSQLに似た言語を利用することもできる(HybernateのHQLのようなものと思われる)。また、SQLを直接発行することもできる。
今回はLINQtoEntitiesでの参照、EntitySQLでの参照、EntityFrameworkでの更新を試した。

サンプルコード

        private static void EntityFrameworkSample()
        {
            // Entity SQLでの参照
            Console.WriteLine("-- Entity SQL");
            using (EntityConnection connection = new EntityConnection("name=SampleContext"))
            {
                connection.Open();

                string query1 = "SELECT m.id, m.name, m.age FROM SampleContext.member AS m WHERE m.age >= @age";

                using (EntityCommand cmd = new EntityCommand(query1, connection))
                {
                    cmd.Parameters.AddWithValue("age", 25);

                    using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
                    {
                        while (rdr.Read())
                        {
                            Console.WriteLine("id={0},name={1},age={2}", rdr["id"], rdr["name"], rdr["age"]);
                        }
                    }
                }

            }

            using (var db = new SampleContext())
            {
                // LINQ to Entitiesでの参照
                Console.WriteLine("-- LINQ to Entities");
                var query1 = from m in db.member
                             where m.age >= 25
                             select m;

                foreach (var member in query1)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // 別の書き方での参照
                Console.WriteLine("-- LINQ to Entities 2");
                var query2 = db.member.Where(m => m.age >= 25);

                foreach (var member in query2)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // Entity Framewokでの更新
                var carol = db.member.Find(3);
                carol.age = 60;
                db.SaveChanges();
            }
        }

Dapper

シンプルなORM(Micro-ORM)で、StackOverflowの中の人が作ったらしい。
Commandの作成やオブジェクトへのマッピングなど、定型的で面倒な部分を補ってくれる。重厚なORMはいらないけど生ADO.NETもちょっと・・・というケースに。

導入方法

NuGetで"Dapper"をインストールする。
EntityFramework6.2が入っている状態ではインストールできなかったので、EntityFrameworkは6.1.3にしておく。

サンプルコード

マッピング先のクラスはEntityFrameworkが作成した下記クラスを流用。

    public partial class member
    {
        public int id { get; set; }
        public string name { get; set; }
        public int age { get; set; }
    }

実際の処理は下記。

        private static void DapperSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // Dapperによる参照
                string selectquery = "SELECT id, name, age FROM member WHERE age >= @age";
                var members = connection.Query<member>(selectquery, new { age = 25 });

                foreach (var member in members)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // Dapperによる更新
                string updatequery = "UPDATE member SET age = 30 WHERE id = @id";
                connection.Execute(updatequery, new { id = 3 });
            }
        }

その他

気になって調べた事柄をメモ。

LINQ to EntitiesとLINQ to SQLの違い

下記がわかりやすかった。
c# - What is the difference between "LINQ to Entities", "LINQ to SQL" and "LINQ to Dataset" - Stack Overflow

引用すると、下記の通り。

・すべてLINQ(Language Integrated Query)であるため、共通点は多い。これらの"方言"は、異なるデータ元に対するクエリの書き方を提供する。
・LINQtoSQLはMicrosoftの最初のORMへの試みだが、SQLServerにしか対応していない。SQLServerのテーブルと.NETオブジェクトのマッピングを行う。
・LINQtoEntitiesは同じMicrosoftによるORMだが、EntityFrameworkを背景に利用し、複数のDBMSに対応している。

まとめ

ADO.NET周りは(たぶん歴史的な経緯のためと思われるが)似たような用語、概念が多く、最新の技術セットが何なのか把握するのが難しく感じた。
今回の理解としてはMS的にはEntityFramework(LINQ to Entities)で、他の選択肢としてOSSを考えるという形なのだけど合っているのだろうか・・。
Dapperも簡単に使えて良さそうだが、MS系ではなんとなくMS流儀に乗っかりたくなるので、まずはEntityFrameworkを使ってみようかな。

DockerForWindowsで開発用SQLServerを利用する

はじめに

.NETアプリケーションを作るのにSQLServerを利用しようと思ったが、
クライアント環境を汚さないように、勉強も兼ねてDockerで稼働させることにした。
今回はSQLServer Developer 2017を稼働させる。
Docker体験も兼ねてるので、Docker知ってる人なら当たり前・・という内容も含まれているので注意。

なお、このページの内容は下記ページに基づいています。
https://hub.docker.com/r/microsoft/mssql-server-windows-express/

環境

  • Windows10 Professional
  • SQL Server Management Studio 17.3(クライアント環境を汚さないようにと思うが、やはりSSMSは欲しい)
  • Docker CommunityEdition 17.09.1-ce-win42 (14687)

DockerForWindowsの導入

本題ではないが簡単に記載。Windows10の場合、Professional以上のエディションが必要。

  1. Windowsの機能の有効化より、「Hyper-V」、「コンテナー」をインストール
  2. Docker for windowsをインストールする。(https://docs.docker.com/docker-for-windows/install/)
  3. DockerをWindowsContainerモードにしておく(タスクトレイを右クリックしてSwitch to Windows containers...)
  4. PowerShellタブ補完のインストール(任意)
    • PowerShellで>Install-Module posh-dockerする
    • "Import-Module posh-docker"をprofile.ps1に追加する。

imageの取得

サイズも大きいので、一旦imageを取得しておく。サイズは11.6GBとなかなか大きい。
expressの場合はmicrosoft/mssql-server-windows-expressをpullする。

docker pull microsoft/mssql-server-windows-developer

コンテナの起動

環境変数として下記を指定する。

ACCEPT_EULA・・・利用許諾契約に同意するかどうか。Yで指定。
sa_password・・・管理ユーザー(saユーザー)のパスワードを指定。複雑性の要件あり。
attach_dbs (任意)・・・dbName(DB名)、dbFiles(mdf,ldfファイル)を指定。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

オプションの意味は下記。
d・・・デタッチドモード。ルートプロセスが終了したらコンテナも終了する。
p・・・[ホスト側ポート]:[コンテナ側ポート]でポートフォワードする。
e・・・[変数名]=[値]で環境変数を指定。
SQLServerインスタンスは通常1433ポートを利用する。

この段階で、localhost:1433にsaユーザーで接続可能となる。

コンテナの停止・終了

コンテナの停止は、docker stop。(32fad42ed443は"docker ps -a"で確認可能なコンテナID)
数分かかかる。

docker stop 32fad42ed443

コンテナの再開は、

 docker start 32fad42ed443

停止、再開であればデータは保持される。

コンテナの削除は停止後に、

docker rm 32fad42ed443

コンテナ内のデータが消えるため、データを永続化したい場合は注意。

データの永続化

システムDBなどは、コンテナ側の下記フォルダに保存される。
C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA

新しいDBを作成する場合もコンテナ内のフォルダパスを指定する。
f:id:endok:20171229144029p:plain

ただしこのままでは、上記の通りコンテナ削除時にデータが消えてしまう。
永続化するには、ホスト側のフォルダをvオプションでコンテナにマウントする。
下記のようにすると、ホスト側のc:/Users/hoge/work/docker-mssql/dataをコンテナ側のC:/DATAにマウントする。C:\Data以下にmdf,ldfファイルを作成することでコンテナを削除してもデータが消えなくなる。
Windowsのボリューム指定方法はぐぐると色々書き方があったが、私の環境では下記の書き方で通った。)

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y  -v "c:/Users/hoge/work/docker-mssql/data:C:/DATA" microsoft/mssql-server-windows-developer

作成したmdf,ldfファイルを読み込んだ状態でコンテナを起動するには、下記のようにattach_dbs環境変数を指定する。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y -e attach_dbs="[{'dbname':'testDB','dbFiles':['C:\\DATA\\testdb.mdf','C:\\DATA\\testdb_log.ldf']}]"  -v "c:/Users/hoge/work/docker-mssql/data:C:/DATA" microsoft/mssql-server-windows-developer

デフォルトのC:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATAにマウントできたらいいなぁと思ったが、思ったようにマウントできず断念。半角スペースの前を\でエスケープしたらコンテナ起動はできたが、何か違う場所をマウントしてしまっているのか、DB作成してもファイルができなかった。
もともとシステムDBのファイルなどあるので、だめなのかも??よくわからず。

その他

パスワード複雑性要件

saパスワードを簡単なもので起動してみる。
→コンテナ起動はするが、SSMSからログインできず(認証NGぽいエラー)。おそらく8文字以上、英数大小記号から3種などが必要。

docker run -d -p 1433:1433 -e sa_password=pass -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

ACCEPT_EULAをY以外にする

ACCEPT_EULAをY以外にしてみる。
→コンテナ起動はするが、SSMSから接続できず。SQLServerのサービスが起動していないような雰囲気。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=N microsoft/mssql-server-windows-developer

まとめ

Windows環境でのパス指定の方法がわからず少し試行錯誤した。Docker操作に慣れるとコンテナの作成、削除がサクサクできて、コンテナ起動も想像より早く、環境を作ったり壊したりがここまで簡単にできるのはかなり新鮮だった。
若干気になるのが、パフォーマンスはどのくらいDocker越し(Hyper-V越し?)で変わるんだろうか。IISもDocker起動したら結構重いのかな。あとはイメージサイズで、自宅PCならまだしも社用PCは潤沢とは言えないディスク容量なので、実用できそうなのはちょっと先かなー。

PowerShellでフォルダ比較を行う

PowerShellの中でフォルダの中身を再帰的に比較したいことがあったため、調べた結果をメモ。

diffコマンドがあればこんな苦労はないのだが、PowerShellWindows標準のコマンドだとかゆいところに手が届かない感じ。
GUIならWinMergeがあるが、今回はPowerShellスクリプトから利用したい。

ググると、下記情報が出てくる。
stackoverflow.com

コードとしては下記の通り。

$d1 = get-childitem -path $dir1 -recurse
$d2 = get-childitem -path $dir2 -recurse
compare-object $d1 $d2

Get-ChildItemで比較する2フォルダを取得して、そのままCompare-Objectに渡している。
このやり方を試してみると特徴は、

  • ファイルの有無を比較できる
  • ファイルの内容の比較はできない
  • 同一ファイル名が別階層に存在していると差分なし扱いになってしまう

といったところ。
同一ファイル名の別階層を差分なし扱いにするため、今回は下記のように改変して使ってみた。

$d1 = (Get-Childitem -Path $dir1 -Recurse | % { $_.FullName.Replace(("$dir1" + "\"), "") })
$d2 = (Get-Childitem -Path $dir2 -Recurse | % { $_.FullName.Replace(("$dir2" + "\"), "") })

compare-object $d1 $d2

ファイルリストの比較はこれで問題なさそう。
本当はファイル内容の比較も行いたかったがそちらは簡単な書き方が結局見つけられず、普通にループしながらCompare-Objectをひたすら実行することに・・・。

Spring Boot触ってみる その5 ープロファイルを利用した環境ごと設定の切り替えー

Spring Boot触ってみる その4 ーSQLServerへの接続ー - endokのブログ
の続き。

DB接続設定など、実行する環境に応じて切り替えたいパラメータがある。
Springでは"Profile"という仕組みで切り替えることができる。

その1(http://endok.hatenablog.com/entry/2016/06/04/124011)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む

Spring Boot触ってみる その4 ーSQLServerへの接続ー

Spring Boot触ってみる その3 ーThymeleaf Layout Dialectでレイアウトを共通化ー - endokのブログ
の続き。

SpringBootでのSQLServerへの接続方法を確認する。
SpringBoot特有の設定ということはなく、Springであれば同じような設定となるだろう。

その1(http://endok.hatenablog.com/entry/2016/06/04/124011)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む

Springで定義済のBean名一覧を出力する

SpringBootはSpringのBean設定を隠蔽してくれているのだが、SpringBoot側で定義しているBeanをInjectionしたいときにはどういったBeanが定義済なのかわからず困る。
定義済のBean名をすべて出力する方法を調べたのでメモ。

方法は下記の通り。

1. BeanFactoryAwareをimplementsして、BeanFactoryを取得する。
2. BeanFactoryをDefaultListableBeanFactoryにキャストして、getBeanDefinitionNamesメソッドを利用する。

Controllerで実装した場合の例はこのようになる。

@Controller
public class HelloController implements BeanFactoryAware {

	private DefaultListableBeanFactory beanFactory;
	
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = (DefaultListableBeanFactory)beanFactory;
		
	}

	@RequestMapping(value = "/page1")
	public String page1() {
		
		for (String name : beanFactory.getBeanDefinitionNames()) {
			System.out.println(name);
		}
		
		return "page1";
	}
	
}