この記事の目的
この記事は、
EF Coreが出力する実際のSQLの検証を行うこと
を目的としています。
今回は、Selectに焦点を絞って、いろいろな条件でクエリを投げた結果をまとめていきます。
前回は、クエリ式、メソッド式どちらもやりましたが、今回からしばらくは、クエリ式中心でまとめていきます。
実行環境などは、前回のブログと同じものを利用しています。
変更点
AccountテーブルにNote列を追加しました。
本題
WHERE句 Null検索
NotNull制約が付いたEmail列と、制約が付いていないNote列に対して、以下のようなクエリを投げてみます。
(from account in context.Account where account.Email != null && account.Email != string.Empty && account.Note != null && account.Note != string.Empty select account).ToList();
結果・・・
SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE((a.email <> '') AND (a.note IS NOT NULL)) AND(a.note <> '')
- 1つの区切りごとに括弧がつけられるので、どこまでが一つの条件かわかりやすくなっています。条件が3つ(A、B、C)ある場合、 (A and B) and C のような形式で付与されているようでしす。条件が4つ(A、B、C、D)ある場合、 ((A and B) and C ) and D になるイメージですね。こうしている理由は何だろう・・・こうしたほうがパフォーマンスがあがるのかなぁ。
- Email、Noteどちらの列にも、Nullに関するチェック処理を追加しましたが、Emailのほうの条件だけ無視されています。
- から文字列でないことの確認は、どちらの列も同じように出力されました。
Null が無視される件については、DBContextクラスのRequire設定が影響を与えていました。自動生成されたDBContextクラスの設定を以下のように変更することで、Null条件が無視されずに出力されることを確認しました。※無理やり出す必要もないですね(´▽`)
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Account>(entity => { entity.Property(e => e.Email) //.IsRequired() <- Here .HasColumnName("email") .HasMaxLength(355); entity.Property(e => e.Note) .HasColumnName("note") .HasColumnType("character varying"); }); }
SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE (((a.email IS NOT NULL) AND (a.email <> '')) AND (a.note IS NOT NULL)) AND (a.note <> '')
WHERE句 Null検索 with String メソッド
文字列の値が、Nullであること、空文字列であることを確認するときにお世話になるメソッド・・・そう、String.IsNullOrEmpty。これを使って、同じようにEmailとNote列の比較を行ったらどうなるか、調べてみました。
//IsNullOrEmptyを使った場合 SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE a.email = '' //IsNullOrEmptyを使った場合 SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE (a.note IS NULL) OR (a.note = '') //IsNullOrWhiteSpaceを使った場合 SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE BTRIM(a.email, E' \t\n\r') = '' //IsNullOrWhiteSpaceを使った場合 SELECT a.user_id, a.created_on, a.email, a.last_login, a.note, a.password, a.sex_id, a.username FROM account AS a WHERE (a.note IS NULL) OR (BTRIM(a.note, E' \t\n\r') = '')
- Stringクラスのメソッドを使った場合も、NotNull制約がある列に対しては、Nullの検査が無視されました。
- String.IsNullOrWhiteSpaceを使った場合、文字列から、特定の文字列を削除した後の結果に対して、空文字検索が行われました。特定の文字列は、半角スペース、タブ、改行、キャリッジリターンの4つが含まれています。全角スペースは、含まれていません。ちなみに、以下のように、C#でのString.IsNullOrWhiteSpaceでは、全角スペースも含まれています。ここは、気を付けないといけないポイントですね!
string.IsNullOrWhiteSpace(null) // →true string.IsNullOrWhiteSpace(string.Empty) // →true string.IsNullOrWhiteSpace(" ") // →true string.IsNullOrWhiteSpace(" ") // →true string.IsNullOrWhiteSpace("あ") // →false