サポンテ 勉強ノート

サポンテの勉強ノート・読書メモなどを晒します。

LINQ テクノロジ入門

はじめに

前回の記事を書いた後で LINQ についてちゃんと身につけたかったため、この本を読んでみました。

LINQ は様々なネット情報だけを見てなんとなく使っていて、モヤモヤ部分があったのでスッキリしました。

LINQ とは

漠然と「集合1を加工する機能」だと思っていましたが、ネット情報にはいずれもそのようなことは書いておらず、探せば探すほどモヤモヤが募っていました。

この本にはそれがズバリと書かれていて、ああやっぱりその理解で良いのかと、やっと腑に落ちた次第です。

本の紹介

全部で 250 ページほどと短めです。手を動かしながら進める部分があるため、そこは少し時間がかかりますが、3日もあれば終えることはできるでしょう。後述の読む部分だけなら1日で済みます。それだけでももちろん強力です。

全体的に LINQ to SQL の情報が多く、手を動かしながら進める部分は LINQ to SQL の操作が大半です。LINQ to SQLSQL とは、ここでは Microsoft SQL Server のことを指していて、残念ながら一般的な意味での RDBMS ではありません。LINQ to SQLSQL Server に格納されているデータに LINQ でアクセスするためのプロバイダ(ドライバ)です。私は現在、業務に SQL Server をつかっていないため、この部分については参考にならず興味も持てなかったので読み飛ばしました。反対に、SQL Server を業務で使用しているかたには実りがあるでしょう。

LINQ はもちろん SQL Server の世界に留まらない技術なので、読んだ価値は十分にありました。

この本の読みかた

一章から三章までと「8.3 ラムダ式の展開」を熟読し、五章から七章は手を動かしながら進め__そして実開発ではリファレンスのように使い__残りの部分に目を通す。そのような読み方になるかと思います。

私は前述の通り、五章から七章は業務に関係ないので読み飛ばしさせていただきました。

この本での呼称

前回の記事で書いた LINQ の二つの構文「クエリ構文」と「メソッド構文」は、この本ではそれぞれ「埋め込みクエリ方式」「拡張メソッド方式」と呼称されていました。まあ当たらずしも遠からずだし、なんだか長いので特に訂正しないでおきます。

LINQ の導入に当たって追加された機能

一章から三章までは概念的な読み物になっていますが、サンプルコードが多用されていてとてもスムーズに頭に入ってきます。

LINQ の導入にあたって C#VB それぞれに導入された新しい概念について LINQ と関連しながら説明がありました。いずれも柔軟で強力な機能ですが、落とし穴を作りそうな機能でもあるので LINQ の文脈以外で濫用しないようにとの戒められています。この一文はぜひこの本を実際に手に取って読んでほしいです。

匿名データ型

Dim a = New With {.Name = "Nobu", .Age = 33}

VB.NET で上記のようにとすると変数 aコンパイラが自動的に匿名クラスのオブジェクト型として扱ってくれます。なんとエディタのコード補完も効きます。C# では var キーワードで作成する変数です。

LINQ とともに導入されたもので、かつての Variant 型のようなものではありません。

自動プロパティ

public class Employee
{
    public string Name {get; set;}
    public int    Age {get; set;}
}

知ってると思いますが C# で上記のように記述するとコンパイラが自動的に private なフィールドを作成してくれます。

この機能は VB.NET にはありません。

オブジェクト初期化子

オブジェクト初期化子は、コンストラクタを持っていないクラスでも同時に初期化ができる記述法で、VB.NET では以下のように記述します。

Dim a As New Employee With {.Name = "Nobu", .Age = 33}

拡張メソッド

Dim a As Integer() = {1, 2, 3}
Dim b As Integer = a.Sum()          ' 結果、変数 b は 6 になる。

上のコードの二行目にある Sum() は、これまでの感覚だと Integer() のメソッドのように思えますが、LINQ ライブラリによって提供されている「拡張メソッド」だとのことです。

外部からメソッドを追加するという、オブジェクト指向の理念に反したものなので LINQ 以外で濫用しない旨、この本では戒めています。

パイプライン処理(RDBMS との違い)

RDBMS の SELECT は、データの集合から別のデータの集合へと加工します。それに対して LINQ は、データの集合をパイプライン処理で加工するものです。そうして LINQ で加工した結果は、やっぱりデータの集合である場合もありますが、オブジェクトだったりすることもあります。

上記の Sum() のコード例では整数の集合(配列)から整数へと加工しています。

パイプライン処理というよりメソッドチェーンと言った方が理解しやすいかたもいるかもしれません。

RDBMS では最初に抽出後の列を SELECT 句の下に書きますが、LINQ はパイプライン処理なので、最初に「どのデータ集合を加工するのか」を指定しなければなりません。これは RDBMS では FROM 句で指定するものです。そこから「データ集合から抽出する内容は何か」を指定する WHERE が続きます。LINQ クエリで SQL の SELECT 文とは Select, From Where の登場する順序が異なるのは、このパイプライン処理に由来するものであるためということがよくわかります。

LINQ の二つの記述法のうち、パイプライン処理(メソッドチェーン)であることが明確にわかる「拡張メソッド方式」の採用を、この本でも勧めていました。なじみのある SQL からへだたりがある理解し難い LINQ の記法も、こうした説明があればとても理解しやすいものだと感じました。

ソートの方法・JOIN の方法

ソートや結合など、気がかりだった機能とその記法についても知ることができました。ハンズオンはしていませんが五章から七章にかけて、LINQ のさまざまな機能についての詳説があり、とても役に立ちました。

説明は割愛します。役に立つ本なので手元に置いても良いでしょう。

おわりに

「入門」とありますが LINQ 以外については「.NET Framework の他の機能についてはもう知っているよね」というスタンスで書かれた本です。Amazon にもそのような旨のレビューがありました。全くの初学者が手に取っても、確かにつらいでしょう。しかし業務である程度(数年?) .NETRDBMS に触れたことがあれば読み進めることができると思います。

本記事も含まれると思いますが、ネット情報では、やはり圧倒的に情報が不足しています。ぜひ実際にこの本を手に取って読んでみてください。


  1. .NET の世界では「コレクション」と言った方が解りやすいかもしれません。

SQL - LINQ コード対比

はじめに

統合言語クエリ - Wikipedia

.NET 3.5 で導入された新しい(当時)構文ですが、ほとんど使ったことがありませんでした。

理由としては以下のような感じになります。

使いどころが無い。

そもそも使いたいと強く感じる場面がありませんでした(少なくとも今までは)。入門記事を読んでみても、その魅力をずいぶん強調してはいるものの、適用シーンが思い浮かびません。

ネットのサンプルが C# ばかり

現在の職場では VB.NET 主流です。同じ .NET なので C# のコード査読も基本的には苦にならないはずなのですが、しかし LINQ は新しい(当時)概念であり、構文もこれまでと大きく異なる(ように見える)ため、同じようには読めません。

ネット上のサンプルに添えられた説明だけでは不足していてよくわからず、逆に詳細なものは理論が先行しすぎていて、実際の使い方がよくわからないという状況でした。

SQL 憎しの説明が多い

どうも「SQL を使わなくてもいい」とか「なじみの無い SQL に似た構文もあるけど、そっちは使わなくても書ける」といった説明が多く見受けられました。

私としては SQL の方がずっとなじみがあるものなので、そうした説明はむしろバリアになります。「SQL ではこう書くところ、LINQ ではこう書く」という、私にとって解りやすい説明がなかったのです。

また後日感じたことですが、C# では SQL に似たクエリ構文よりも、メソッドチェーンのように書ける構文の方がすっきりとしていて好まれるのに対して、VB ではクエリ構文の方がすっきりしています。この点では時代を経るごとに両者の文化の溝が深まっていきそうな感じがします。

使いたいところ

自分の思いつく使いどころは「SQL で採ってきたデータを、いろいろ編集してから集計したりソートしたりしたい」というものでした。既に SQL の世界を離れ .NET の世界にあるデータテーブル(System.Data.DataTable)に対して SQL を発行するような気楽なイメージで使いたいのです

複雑なサブシステムが多く、あちこちからデータを取得し、最終的に集計をしたい場合、SQL だけでは望むものが作れません。

また経験上、サブクエリを駆使してデータベースへの問い合わせ回数を減らすよりも、取得したいデータを VB.NET の世界に持ってきてからプログラムで操作をした方がパフォーマンスが出る場面も多かったので、そのような場面でも LINQ が威力を発揮すると考えました。

コード対比サンプル

ではその「SQL ではこう書くところ、LINQ ではこう書く」の対比サンプルを掲載しておきます。

ユースケースとしては、以下の SQL で行うような集計を、データテーブルに対して行うことを想定します。

SELECT
      theID         AS product_code
    , SUM(price)    AS summary_price
FROM theTable
WHERE 1=1
    AND discontinue = 0
    AND disabled_date IS NULL
GROUP BY
    theID
ORDER BY
    theID

続いてデータテーブルから同様に集計データを抽出する LINQ サンプルです。データテーブル「 dt 」には SELECT theID, price FROM theTable の結果のようなものが入っていると想定します。

Imports System.Data

' 中略

Dim dt as DataTable

' 中略

Dim olinq As Object

olinq = From dr As DataRow In dt
        Where 1 = 1 _
            AND dr("discontinue") = 0
            AND dr("disabled_date") Is DBNull.Value
        Order By dr("theID") Ascending
        Group By
            product_code = dr("theID")
        Into
            summary_price = Sum(CInt(dr("price")))
        Select New With {
            .ProductCode = product_code
            .SummaryPrice = summary_price
        }

For Each row As Object In olinq
    System.Diagnostics.Debug.Print(row.ProductCode & " " & row.summary_price)
Next

最後の Select 句の中で無名オブジェクトに初期化していますが、特定のクラスにも出来ます。

Class ProductObj
    Public ProductCode As String
    Public SummaryPrice As Integer
End Class

' 中略

olinq = ... ' 中略
        ' ... 略
        Select New ProductObj With {
            .ProductCode = product_code
            .SummaryPrice = summary_price
        }

For Each row As ProductObj In olinq
    System.Diagnostics.Debug.Print(row.ProductCode & " " & row.summary_price)
Next

免責

サンプルは、説明のために要点以外は省略しています。そのままでは動作しません。

終わりに

LINQ は今までと勝手が違うので、まずはなじみのある書き方で挙動を確認してから、理論的なものを追いかけていけば取っ付きやすいかなと思います。

やっと LINQ のスタート地点に立てた感じです。

Git の差分を簡易的に確認するエディタ機能 Git Diff Margin ? VCS Gutter ?

はじめに

仕事の内容や環境によって、使いたい・使うことが出来るエディタや IDE が変わってくることがあります。様々のエディタには似たような機能が実装されていますが、それぞれ呼称が異なる場合があります。調べるとき「○○エディタの××という機能を△△ IDE でも使いたいのだが、それはどう言うのだろうか」と、呼称がわからず困ることがあります。

今回は Git の差分を簡単に表示する機能を集めてみました。一つの記事にまとめておけばなんらかのキーワードに引っかかって誰かの役に立つかもしれません。

どんな機能のことを言っているのかイメージが沸かない方は、最初の NetBeans のリンク先をご覧ください。

エディタと機能名称

NetBeans

標準機能。

ソース・エディタでの変更の表示

見た目がすっきりしていて好きです。

Visual Studio

プラグイン

Git Diff Margin

この名前が一番あたまに残っています。

Visual Studio Code

標準機能。

Git Gutter Indicator

IntelliJ IDEA

標準機能。

Change Markers

Eclipse

標準機能。

クイック Diff

一番しっくり来る名前です。

Xcode

プラグイン

GitDiff

Atom

プラグイン

Sublime Text

プラグイン

GitGutter

Emacs

プラグイン

git-gutter.el

Vim

プラグイン

vim-gitgutter

「セキュリティのみの更新プログラム」が毎月失敗する

はじめに

私の環境に限るかもしれませんが、必ず「セキュリティのみの更新プログラム」が毎月失敗します。しかし、その後の成功するパターンが見えてきたので記します。

状況

月例の「セキュリティのみの更新プログラム」をインストールして再起動すると更新に失敗して復元されます。

解決方法

先に「悪意のあるソフトウェア削除ツール」を適用します。

複数のアップデートがリストアップされている場合「セキュリティのみの更新プログラム」を除くアップデートを先に適用します。

1. 他のアップデートがないかどうか確認する

自動更新にしている場合、配布済みの全ての更新プログラムが表示されていない可能性があります。とくに会社に貸与されている PC をお使いの場合、その会社のポリシーによって更新頻度とその内容が一律に決められていることが多いはずです。こうしたときに、一覧されるものに「漏れ」が発生し「悪意のあるソフトウェア削除ツール」が表示されていない場合があります。

Windows Update からの更新プログラムをオンラインで確認する」をクリックして、現在適用されていない更新プログラムが他にないかどうかを確認します。

2. 他のアップデートを先に適用する

各更新プログラムは適用するかどうかをユーザーが選択できます。その機能を使って、失敗する更新プログラムを除外し、他のアップデートを先に適用します。

3. 失敗したアップデートを適用する

他のアップデートが適用し終わったら、いよいよ目的のアップデートを適用します。

おわりに

環境は人それぞれ全く異なるので一般化できないかもしれません。特に更新プログラムの適用済・未済まで絡んでくると、もはや混沌の世界です。

同じように更新失敗する PC がこの手順で上手くいくかどうかは保証できません。しかし私の環境では「悪意のあるソフトウェア削除ツール」->「セキュリティのみの更新プログラム」の適用には順序の依存性がありました。

また、調べた結果出てきたさまざまのトラブルシューティングツールは効果がありませんでした。

この情報が同じようなことで困っている人の一助になれば幸いです。

PHP の正規表現(PCRE)に入門してみる

はじめに

試験勉強です。

今回は見事に全部スニペットになってしまいました。

PHP のマニュアルに掲載されているサンプルはコメント部分が翻訳されていなかったり「日本語を処理する場合はどうなるのだろう」という細かいことがわからなかったりします。

いずれにしても、手を動かして細かい挙動を探ってみないといけないのは、どの言語でも同じです。

今回はテキスト処理なので例文を考えてみるのも少し楽しかったです。

続きを読む

PHP における XML-RPC について入門してみる

はじめに

試験勉強です。

XML-RPC については、マニュアルがとても心細いので勉強するのもたいへんです。

こちらこちら を参考に、できるだけ簡単なスニペットにしてみました。

続きを読む

PHP における XPath の扱いについて入門してみる

はじめに

PHP + XML の試験勉強の続きです。

一つのサンプルになるべく DOMXPath クラス のメソッドを詰め込んでみました。

と言っても5つですが。

続きを読む