LINQでエラー!?「linq to entities では認識されないため、ストア式に変換できません」の対応方法とその理由(The LINQ expression ○○ could not be translated)【C# linq】

Linqを使用したコードを書いていると、定義した関数でエラーになることがあります。

たとえば、次のようなコードの時


これは単純に生徒の中から「Laura」という名前の生徒のリストをつくろうとしているコードです。
しかし、使っているEntity Frameworkなどにもよりますが、

linq to entities では認識されないため、ストア式に変換できません

The LINQ expression ○○ could not be translated

などのエラーが発生します。

そこで今回は、これらLINQに関わるエラーで困っている方向けに、
対処法とエラーが発生する理由について紹介します。

対応方法:自分で定義した関数を使う前にToList ,ToListAsyncを使う

早速ですが、エラーの回避方法です。


このように自分の関数を使うまえに先にToListをしてしまうことが一つの解決策になります。

ToListで解決できる理由(データベースにアクセスしないから)

そもそも何故ToListを間に挟むだけで解決できるのでか、
理由を次のようにみていきましょう。

  • LINQはデータベースとC#コードの両方あつかえる
  • 原因はデータベースで存在しない関数をさがしている
  • ToListでデータベースへの問い合わせをOFFにする

LINQはデータベースとC#コードの両方あつかえる

LINQは統合言語クエリともいいます。

統合」は、何と何を統合しているのでしょうか。

今回の場合はつぎの2つです。

  • データベース上のテーブルデータ
  • メモリ上のListデータ

テーブルデータもListデータも存在している場所が違うだけで構造はとても似ています。

つまり、「扱うデータが似ているなら、扱い方も同じでいいじゃない→同じコードで動かそうという」
この技術こそLINQなのです。

原因はデータベースで存在しない関数をさがしている

おなじコードで動かそうとしているのであれば、何故エラーがでているのか。

そもそもC#で書いた貴方のコードはプログラム上でエラーが発生しているのではなく、
データベースで起きているからです。

コードの内容と場所が重要です。

先に例に出した「isLaura()」関数はLauraさんを抜き出す関数です。
しかし、この関数はプログラム上にしかありません

データベースにLINQで問い合わせたところで、
「クエリに変換できませんでした」というのが冒頭のエラーたちになります。

linq to entities では認識されないため、ストア式に変換できません

The LINQ expression ○○ could not be translated

ToListでデータベースへの問い合わせをOFFにする

データベースとのつながりのある時はすべて、データベースにクエリの形でアクセスします。
プログラムでデータベース上にあるデータを扱うには、
プログラム側に持ってくる必要があります。

それを行うのがToList(またはToListAsync)です。


ToListを行うと、その時点で取得するデータを持ってきます。
すると主戦場がC#のコードになりますので、自分で定義した関数を使うことができます

LINQがデータベースのクエリになるかどうかの見分け方

とは行っても、自分で定義した関数がListに対してもデータベースに対しても使えるように見えるのは事実、
では、見分け方はどうするのか

それは、LINQメソッドの型でわかります。

  • IQueryable:データベースへのクエリになる、用意されている関数や比較が基本
  • IEnumerator:データベースへのクエリにならない、自分で定義した関数が使える


visual studioをお使いであれば、Whereメソッドなどにマウスオーバーで確認できます。

まとめ

簡単にこの記事をまとめます。

  • 自分でつくった関数がLINQで使えなかった時はIQueryableかどうかを確認して、
    クエリに変換できるのかどうかで考えよう
  • 変換できないようであればToList,ToListAsync()をしてから自分でつくった関数を使おう

LINQはとても便利です。

LINQがない言語はデータベースに対してクエリを書かなければなりませんが
LINQはList操作と同じ書き方でSelect操作などデータベース操作ができます。

テーブルの操作とListの操作を同じ書き方ができるとシンプルになるメリットがあります。

しかし、今回のエラーは便利がゆえにハマりやすいポイントなので、注意したいところですね。

では。