ひどくピンポイントかつ3時間ほどハマってしまったので、メモ書き的に残しておく。
環境は、
- ASP.NET Core
- .NET Core 1.1
- EF Core を利用
ASP.NET Core で Web API を作っていて、ローカルの .NET Core で LINQ の Join が動いていたのだが、いざ Azure にアップロードして動作させると、Join 部分がうまくいかなくて意味不明なエラーを返した。
1 2 3 4 5 6 7 8 | var cnt1 = ( from ti in _context.TicketView join st in _context.Status on ti.Status_Id equals st.Id where ti.ProjectId == project.Id && ti.Tracker_Id == tr.Id && st.IsClosed == false select ti.Id ).Count(); |
とあるところで、こんな風に TicketView と Statues テーブルを JOIN させた。何をやりたかったかというと、Statues テーブルの IsClosed フラグを見て、その数をカウントしたかったのだ。これを、ローカル PC の ASP.NET Core で動作させると、するすると動いたので、そのまま Azure に乗せてみると…
テーブル構造が違っているからマイグレーションしろ、
というお達しが来る。最初は、エラーの意味が解らなくて四苦八苦したのだが、少しずつ障害を絞り込んでいくとここの JOIN 部分に至った。この JOIN を消してしまって、var cnt1 = 0 とすると動作することが分かったので、あれこれやって、
1 2 3 4 5 6 7 8 9 | var status = _context.Status.OrderBy(x => x.Position).ToList(); var ticketviews = _context.TicketView.Where(x => x.ProjectId == project.Id).ToList(); var cnt1 = ( from ti in ticketviews join st in status on ti.Status_Id equals st.Id where ti.ProjectId == project.Id && ti.Tracker_Id == tr.Id && st.IsClosed == false select ti.Id).Count(); |
な風に、一度 List に取り込んでから JOIN するとうまく動くようになった。
LINQ を使ってジェネリックの List 同士を Join させる分には大丈夫と解っているのだが、_context.Status のほう(DbSet<Status> などで DI されている)の Join の動作が不明である。もともと、ローカル PC で DbSet 同士の Join ができちゃうのがおかしいのか、それとも Azure 上の .NET Core で DbSet 同士の Join ができないのがおかしいのか。
どちらにせよ、同じコードをローカル PC と Azure 上で動かしたときに、挙動が違うのは「おかしい」ので、ここは調べないといけない。これ、Linux 上の .NET Core だとどうなのだろうか? 後で調べるか思案中。
追記 2017/05/11
Ubuntu に donet 1.0.3 をインストールして構築してみると、上の Join が動くようになったので、Azure 上だけがダメな模様。
Azure の App Service のコンソールでバージョンを調べると doetnet コマンド自体が 1.0.1 、.net core のバージョンが Version : 1.1.0-preview1-001100-00 になっているので、この違いと思われる。ちなみに、ローカルPC の場合は、1.1.0 になっている。この微妙な差(Azure のほうが previewのままなのが)原因らしい。
Build 2017 の微妙な時期なので、これが終わると 2.0 にアップデートされるかもしれん。
追記 2017/05/19
現時点で、.NET Command Line Tools (2.0.0-preview1-005977) になっているので、join が正常に動いている。やったー。