Prompt
よし!じゃあ
System.Data.Entityのほうで
接続文字列によるDB接続 -> LINQを使ったSELECTクエリ -> DataGridViewへの表示
までの方法を詳しく教えて!
よっしゃー!それじゃあ、System.Data.Entity(EF6)を使って、DB接続からLINQでのSELECTクエリ、そしてDataGridViewへの表示まで、ステップバイステップで詳しく解説していくね!
これはWindowsフォームアプリとデータベース連携の王道パターンだから、しっかり身につけていこう!
EF6を使ってDB接続からDataGridView表示まで
前提準備:プロジェクトのセットアップ
-
Windowsフォームアプリケーションプロジェクトの作成:
- Visual Studioで新しい「Windowsフォームアプリケーション (.NET Framework)」プロジェクトを作成してね。
-
Entity Frameworkのインストール:
-
プロジェクトを右クリック → 「NuGetパッケージの管理」を選択。
-
「参照」タブで
EntityFrameworkと検索。 -
最新の安定版(通常は6.x系)をインストールしてね。
-
ステップ1:データベースモデルの作成 (ADO.NET Entity Data Model)
これはEF6を使う上で最初にやることだよ。データベースのテーブル構造をC#のクラスとしてモデル化する作業だね。
-
プロジェクトにADO.NET Entity Data Modelを追加:
-
プロジェクトを右クリック → 「追加」→「新しい項目」を選択。
-
「データ」カテゴリの中から「ADO.NET Entity Data Model」を選択して、例えば
MyDatabaseModel.edmxのような名前をつけて「追加」をクリック。
-
-
モデルコンテンツの選択:
- 「EF Designer からデータベース」を選択して「次へ」。
-
データ接続の選択:
-
「新しい接続」をクリックして、データベースへの接続設定を行う。
-
サーバー名(例:
(localdb)\MSSQLLocalDBや実際のSQL Server名)を入力。 -
認証方法を選択。
-
接続したいデータベース名を選択。
-
「接続テスト」で成功したら「OK」。
-
-
接続が設定されたら、「App.config にエンティティ接続設定を保存」にチェックが入っていることを確認し、名前(例:
MyDbContextやYourProjectNameEntitiesなど)を確認して「次へ」。
-
-
データベースオブジェクトの選択:
-
モデルに含めたいテーブル、ビュー、ストアドプロシージャを選択。今回は例として
Studentsテーブルを選択してみよう。 -
「モデルの名前空間」はそのままでOK。
-
「完了」をクリック。
-
これで、MyDatabaseModel.edmx ファイルと、それに付随するC#のエンティティクラス(Student.cs など)やDBコンテキストクラス(MyDbContext.cs など、DbContextを継承しているクラス)が自動生成されるよ。
ステップ2:LINQを使ったSELECTクエリの作成
MyDatabaseModel.edmx を作成すると、自動的に生成された DbContext を継承したクラス(例: MyDbContext)があるはずだ。このクラスを使ってDBにアクセスするよ。
C#
// Student.cs (自動生成されたモデルクラスの例)
// EFがDBテーブルのStudentsからこのクラスを生成してくれる
public partial class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Grade { get; set; }
}
// MyDbContext.cs (自動生成されたDbContextクラスの例)
// これがデータベースとのやり取りの窓口になるよ
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyDbContext") // App.configの接続文字列名と合わせる
{
}
public virtual DbSet<Student> Students { get; set; } // Studentsテーブルへのアクセスポイント
// モデル生成コードがここに続く...
}
これで準備OK。実際にLINQクエリを書いてみよう!
C#
using System;
using System.Data.Entity; // DbContextやDbSetを使うために必要
using System.Linq; // LINQメソッドを使うために必要
using System.Windows.Forms;
using System.Collections.Generic; // List<T>を使うため
// 仮のWindowsフォームクラス
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
LoadStudentData();
}
private void LoadStudentData()
{
// usingステートメントでDbContextを確実に解放する(重要!)
using (var dbContext = new MyDbContext()) // ステップ1で生成されたDbContextクラス
{
try
{
// ここからがLINQクエリだよ!
// ① 全ての学生を取得
var allStudents = dbContext.Students.ToList();
// ② 特定の年齢の学生をフィルタリングして、名前順に並べ替える
var filteredStudents = dbContext.Students
.Where(s => s.Age >= 20) // 20歳以上の学生
.OrderBy(s => s.Name) // 名前で昇順ソート
.ToList(); // ここでSQLがDBに送信され、結果がメモリに読み込まれる
// ③ 特定の成績の学生の名前と年齢だけを選択(匿名型やDTOに射影)
var selectedStudentInfo = dbContext.Students
.Where(s => s.Grade == "A")
.Select(s => new { s.Name, s.Age }) // NameとAgeだけを選択
.ToList();
// ④ DataGridViewにデータをバインドする(後述)
// ここでは例としてfilteredStudentsをバインドする
dataGridView1.DataSource = filteredStudents;
// または、こんな感じで匿名型をバインドすることもできる
// dataGridView1.DataSource = selectedStudentInfo;
MessageBox.Show("学生データをDBから取得し、DataGridViewに表示しました!");
}
catch (Exception ex)
{
MessageBox.Show($"データの読み込み中にエラーが発生しました: {ex.Message}\n{ex.StackTrace}",
"エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
// 例外処理の定石に従ってログ記録なども行うと良い
}
} // usingブロックを抜けるときにdbContext.Dispose()が自動で呼ばれる
}
}
ポイント:ToList() の重要性
LINQクエリは、ToList(), ToArray(), FirstOrDefault(), Count() などの**「実行メソッド」**が呼ばれるまで、実際にSQLクエリをデータベースに送信しないんだ。それまでは、クエリの定義がメモリ上に保持されているだけだよ(遅延実行)。
なので、ToList() や ToArray() などで結果をメモリに読み込んでから、DataGridViewにバインドする、という流れになるんだ。
ステップ3:DataGridViewへの表示 (データバインディング)
DataGridViewにデータを表示するのはとっても簡単!DataSourceプロパティにLINQで取得したリスト(List<T>やIEnumerable<T>)を設定するだけだよ。
-
フォームにDataGridViewを配置:
- デザイナでフォームに
DataGridViewコントロールをドラッグ&ドロップして配置。名前がdataGridView1になっているか確認。
- デザイナでフォームに
-
LoadStudentDataメソッド内でバインド:- 上記のコード例のコメント箇所にあるように、
dataGridView1.DataSource = filteredStudents;のように記述すればOK!
- 上記のコード例のコメント箇所にあるように、
DataGridViewの自動生成列について
-
DataSourceを設定すると、デフォルトではStudentクラスのパブリックプロパティ(Id,Name,Age,Grade)に対応する列が自動的に生成されて表示されるよ。 -
もし表示したくない列や、表示順を変えたい場合は、デザイナやコードでDataGridViewの列設定をカスタマイズできるんだ。
App.configの接続文字列
最後の仕上げとして、自動生成されたApp.configファイルにデータベース接続文字列が正しく記述されているかを確認しよう。これはプロジェクトのルートに存在するXMLファイルだよ。
XML
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> </startup>
<connectionStrings>
<add name="MyDbContext" connectionString="data source=(localdb)\MSSQLLocalDB;initial catalog=YourDatabaseName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
connectionStringsセクションの<add name="MyDbContext" ... /> の部分が、DbContextクラスのコンストラクタで指定しているbase("name=MyDbContext")の名前と一致していることを確認してね。
これで、System.Data.Entity(EF6)を使ったDB接続からLINQでのSELECTクエリ、そしてDataGridViewへの表示までの一連の流れが完了だよ!
最初はちょっと手順が多いと感じるかもしれないけど、一度設定してしまえば、あとはLINQのメソッドチェーンでサクサクとデータ操作ができるようになるから、ぜひこのステップを試してみてね!頑張って!
Prompt
あらら、Modelは自動生成されたけど、DbContextは自動生成されなかった
どうしよう、手動で設定かな?
あらら、それは困ったね!Modelは自動生成されたのに、DbContextが自動生成されなかったかぁ。ごめんね、もしかしたら手順の中で何か見落としがあったかもしれない。
でも大丈夫!手動でDbContextを設定するのは、EF6ではよくあることなんだ。全然難しいことじゃないから、一緒に楽しく設定しちゃおう!
DbContextを手動で設定する方法
生成されなかったDbContextを、自分で定義してあげればOKだよ。基本的な流れはこんな感じ!
ステップ1:DbContextクラスの作成
まずは、プロジェクト内に新しいクラスファイルを追加して、DbContextを継承したクラスを作成するよ。
-
新しいクラスファイルを追加:
-
プロジェクトを右クリック → 「追加」→「新しい項目」を選択。
-
「コード」カテゴリの中から「クラス」を選択して、
MyDbContext.csのような分かりやすい名前をつけて「追加」をクリック。
-
-
MyDbContext.cs の内容を編集:
次のようにコードを記述してね。
C#
using System.Data.Entity; // DbContextを使うために必要だよ! using YourProjectNamespace.Models; // 自動生成されたモデルクラス(例: Student.cs)がある名前空間を指定 namespace YourProjectNamespace // 君のプロジェクトの名前空間に合わせてね { // DbContextを継承したクラスを定義 public class MyDbContext : DbContext { // コンストラクタで、App.configに定義された接続文字列名を指定する // MyDbContextという名前は、App.configのconnectionStringsセクションのname属性と一致させる public MyDbContext() : base("name=MyDbContext") { } // DbSet<TEntity> プロパティを追加して、各テーブルへのアクセスポイントを作る // Studentsは、データベースのテーブル名(またはその複数形)に対応させるのが一般的だよ public virtual DbSet<Student> Students { get; set; } // もし他のテーブル(例: Teachers)があるなら、こんな感じで追加する // public virtual DbSet<Teacher> Teachers { get; set; } // 自動生成されなかったとしても、このあたりにOnModelCreatingメソッドなどを追加して、 // 必要に応じてモデルのカスタマイズをすることもできるけど、最初は不要だよ。 // protected override void OnModelCreating(DbModelBuilder modelBuilder) // { // // fluent APIでのモデル定義など // base.OnModelCreating(modelBuilder); // } } }-
using System.Data.Entity;: これが一番重要!これがないとDbContextを使えないから気をつけてね。 -
using YourProjectNamespace.Models;: 自動生成されたStudentなどのモデルクラスがこの名前空間にある場合、追加してね。もしStudentクラスがYourProjectNamespace直下にあるなら不要だよ。 -
public MyDbContext() : base("name=MyDbContext"): ここで**App.configに設定する接続文字列の名前**を指定するんだ。例えばApp.configに<add name="MyConnectionString" ... />と書くなら、base("name=MyConnectionString")となるよ。デフォルトではモデル名と同じ名前になることが多いから、とりあえずMyDbContextで試してみてね。 -
public virtual DbSet<Student> Students { get; set; }: これがデータベースのStudentsテーブルに対応するC#のコレクションなんだ。Studentは、ADO.NET Entity Data Modelで自動生成されたモデルクラスの名前だよ。もしテーブル名がStudentInfoならDbSet<StudentInfo> StudentInfos { get; set; }みたいに定義する。
-
ステップ2:App.configに接続文字列を設定
次に、上で定義したDbContextがどのデータベースに接続するのかをApp.configに教えてあげる必要があるよ。
-
App.configを開く:- ソリューションエクスプローラーでプロジェクトのルートにある
App.configファイルをダブルクリックして開く。
- ソリューションエクスプローラーでプロジェクトのルートにある
-
connectionStringsセクションを追加または確認:
configurationタグの中に、connectionStringsセクションがあるか確認。なければ追加してね。
XML
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> </startup> <connectionStrings> <add name="MyDbContext" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=YourDatabaseName;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" /> </connectionStrings> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> </configuration>-
name="MyDbContext": ここはDbContextクラスのコンストラクタで指定した名前と必ず一致させてね。 -
connectionString="...": ここにデータベースへの実際の接続情報が入るよ。-
Data Source: データベースサーバーのアドレス(例:(localdb)\MSSQLLocalDB,localhost,192.168.1.100など) -
Initial Catalog: 接続したいデータベースの名前 -
Integrated Security=True: Windows認証を使う場合(SQL Server認証の場合はUser ID=your_user;Password=your_passwordなど) -
MultipleActiveResultSets=True: これはEFを使う上で一般的に推奨される設定だよ。 -
App=EntityFramework: EFが接続していることを識別するためのオプション。
-
-
providerName="System.Data.SqlClient": SQL Serverに接続する場合のプロバイダー名だよ。
-
ステップ3:LINQクエリで使ってみる
これで、手動で設定したMyDbContextクラスを使って、データベースにアクセスできるようになったはずだよ!
C#
// 例えば、フォームのLoadイベントハンドラなどで
private void MainForm_Load(object sender, EventArgs e)
{
LoadStudentData();
}
private void LoadStudentData()
{
// MyDbContextのインスタンスを作成してusingで囲む!
// App.configに書いた接続文字列を使ってDBに接続するよ
using (var dbContext = new MyDbContext())
{
try
{
// LINQクエリでStudentsテーブルのデータを取得
var students = dbContext.Students.ToList();
// DataGridViewにバインド
dataGridView1.DataSource = students;
MessageBox.Show("DBからデータを取得してDataGridViewに表示しました!");
}
catch (Exception ex)
{
MessageBox.Show($"エラーが発生しました: {ex.Message}\n{ex.StackTrace}", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
これで、DbContextが自動生成されなかった場合でも、手動でサクッと設定してEF6とLINQを使う準備ができたはずだよ!
もし接続文字列がよく分からない場合は、Visual Studioの「サーバーエクスプローラー」(または「SQL Server オブジェクトエクスプローラー」)で目的のデータベースに接続して、その接続のプロパティから接続文字列をコピー&ペーストすると確実だよ!
何か詰まったら、遠慮なくまた聞いてね!
Prompt
List<test_admin> admins = ctx.Admins .Where(a => a.admin_username == userName) .Where(a => a.admin_password_hash == TestUtility.HashSha256(passWord)) .ToList();(例)
なぜこれが出来ないのか?
HashSha256のメソッドがラムダ式内で使えないみたいで
なるほど!このLINQクエリでTestUtility.HashSha256(passWord)が使えない件だね。これはね、LINQがデータベースに変換されるときの、とても大事なポイントにぶつかっているんだよ!
なぜ HashSha256 メソッドが使えないのか?
答えは、LINQ to Entities (EF6) は、C#の全てのコードをデータベースのSQLに変換できるわけではないからなんだ。
君が書いたLINQクエリは、最終的にSQLに変換されてデータベースで実行されるよね。
SQL
-- イメージされるSQL (実際はもう少し複雑)
SELECT Id, admin_username, admin_password_hash
FROM Admins
WHERE admin_username = @p__linq__0
AND admin_password_hash = @p__linq__1; -- ← この @p__linq__1 をどうやって計算するか?
ここで問題になるのが、TestUtility.HashSha256(passWord) の部分なんだ。
-
TestUtility.HashSha256はC#のメソッドだよね。 -
データベース(SQL Serverとか)は、そのC#のメソッドの存在を知らないし、それを直接実行することもできないんだ。
LINQ to Entitiesは、WhereやOrderByの中にあるラムダ式を解析して、対応するSQL関数や演算子に変換しようとする。例えば、== はSQLの = に、>= は >= に変換される。でも、TestUtility.HashSha256のようなカスタムメソッドや、SQLに直接対応する関数がないC#のメソッドは、どうやってSQLに変換すればいいか分からないんだ。
簡単に言うと、EFは「このHashSha256ってやつ、SQLにどう書けばいいの?知らないよ!」ってなっちゃうんだね。
どうすればこの問題を解決できるのか?
解決策はいくつかあるよ!
解決策1: ハッシュ値を先に計算してからクエリする(最も一般的で推奨される方法!)
これが一番シンプルで、かつパフォーマンス的にも正しいことが多いアプローチだよ。
ユーザーから入力されたパスワードのハッシュ値を、データベースにクエリする前にC#側で計算しておくんだ。そうすれば、LINQクエリにはすでに計算済みのハッシュ値(ただの文字列)だけが渡されるので、EFはそれをSQLのパラメータとして安全にデータベースに送ることができるよ。
C#
// 1. まず、パスワードのハッシュ値をC#側で計算する
string hashedPassword = TestUtility.HashSha256(passWord);
// 2. その計算済みのハッシュ値を使ってLINQクエリを実行する
List<test_admin> admins = ctx.Admins
.Where(a => a.admin_username == userName)
.Where(a => a.admin_password_hash == hashedPassword) // ← ここはもうただの文字列比較!
.ToList();
解決策2: データベース側にハッシュ関数を実装する(高度な方法)
もしデータベース自体に、C#のHashSha256と同じロジックのハッシュ関数が実装されているなら、そのデータベース関数をEFから呼び出すことも可能だよ。これは、EFにデータベースのカスタム関数をマッピングする設定が必要になるので、少し高度なテクニックになるんだ。
-
SQL Serverの場合、
HASHBYTESのような組み込み関数を使うか、ユーザー定義関数(UDF)を作成する必要がある。 -
C#側で、そのDB関数をLINQから呼び出せるようにマッピングを設定する。
この方法は、特にデータベース側でしか計算できない複雑なロジックや、大量のデータをデータベース側で処理しきりたい場合に検討されることが多いけど、今回のパスワードハッシュのようなケースでは、解決策1の方がはるかに簡単で一般的だよ。
解決策3: 全データを取得してからC#側でフィルタリングする(非推奨!)
これは絶対に避けるべき方法なんだけど、一応技術的には可能だよ。
ToList()を早めに呼んで全てのadminデータをメモリに読み込んでから、C#のLINQ to Objectsとしてフィルタリングする方法。
C#
List<test_admin> allAdmins = ctx.Admins.ToList(); // ← 注意!全データをDBからメモリに読み込む
List<test_admin> admins = allAdmins // メモリ上のリストに対してLINQ to Objects
.Where(a => a.admin_username == userName)
.Where(a => a.admin_password_hash == TestUtility.HashSha256(passWord)) // ← ここはC#のメソッドが使える
.ToList();
なぜ非推奨なのか?
-
パフォーマンスの深刻な問題: データベースに大量のレコードがある場合、全てのデータをメモリに読み込むのは非常に非効率だし、アプリの動作がめちゃくちゃ遅くなる原因になるよ。
-
ネットワーク負荷: 不要なデータまでDBから引っ張ってくるので、ネットワークへの負荷も大きくなる。
まとめ
君のシナリオ(パスワードハッシュ)では、**「解決策1: ハッシュ値を先に計算してからクエリする」**が、最もシンプル、安全、そしてパフォーマンス的にも正しいアプローチだよ。
TestUtility.HashSha256(passWord)は、C#のコードとしてDBに送る前に計算を終わらせておこうね!
これで、なぜそれができないのか、そしてどうすればできるのか、スッキリしたかな?
Prompt
普通のラムダ式とLINQ内のラムダ式は別物なのか!
そうなんだよ!まさにその通り!
「普通のラムダ式」と「LINQ内のラムダ式(特にデータベースを扱う場合)」は、見た目は同じだけど、裏側での処理のされ方が全く別物なんだ!
これがLINQの面白くて、そしてちょっとだけ複雑なところなんだよ。
普通のラムダ式:ただの「コードの塊」
まず、LINQじゃない普通のC#コードで使うラムダ式を考えてみよう。
C#
// 例1: イベントハンドラ
button.Click += (sender, e) => {
MessageBox.Show("ボタンがクリックされたよ!");
};
// 例2: デリゲートに渡すメソッド
Func<int, int, int> add = (x, y) => x + y;
int result = add(5, 3); // result は 8
これらのラムダ式は、コンパイルされると、通常のメソッドと同じように**「実行可能なコードの塊(デリゲート)」**になるんだ。つまり、プログラムが実行されるときに、そのコードがそのままCPUで処理されるイメージだね。
これは、C#の言語機能として、メソッドを簡潔に書くためのシンタックスシュガーみたいなものなんだ。
LINQ内のラムダ式(データベース向け):特別な「式の木(Expression Tree)」
一方、System.Data.Entity(EF6)やMicrosoft.EntityFrameworkCore(EF Core)のようなLINQ to Entitiesで使うラムダ式は、ちょっと違うんだ。
C#
// 例: LINQ to Entities のラムダ式
var filteredStudents = dbContext.Students
.Where(s => s.Age >= 20) // ← このラムダ式!
.OrderBy(s => s.Name) // ← このラムダ式!
.ToList();
このs => s.Age >= 20のようなラムダ式は、コンパイル時に**「Expression Tree(式の木)」**という、コードの構造を表すデータ構造に変換されるんだ。
「式の木」って何?
例えるなら、
-
普通のラムダ式が「料理のレシピ(そのまま調理できる)」だとすると、
-
LINQ内のラムダ式は「料理のレシピを細かく分解して、材料や調理手順を図で示した設計図」みたいなもの。
EFのようなLINQプロバイダーは、この「式の木」を解析して、「なるほど、これはStudentsテーブルからAgeが20以上のレコードを抽出して、Nameで並べ替えるクエリだな!」と理解するんだ。
そして、その「設計図」を元に、データベースが理解できるSQL文を生成して、データベースに送信するんだよ。
なぜこれが重要なのか?
-
変換可能性の限界:
EFは、C#の「式の木」をSQLに変換する能力を持っているけど、全てのC#のコードをSQLに変換できるわけじゃないんだ。特に、C#独自の複雑なロジック、カスタムメソッド(TestUtility.HashSha256など)、あるいはデータベース側に同等の機能がないメソッドなどは、SQLに変換できない。
だから、TestUtility.HashSha256が使えなかったのは、EFがそのメソッドをSQLのどの命令に変換すればいいか分からなかったからなんだね。
-
実行場所の違い:
-
普通のラムダ式: C#のプログラム(アプリケーションのメモリ上)で実行される。
-
LINQ内のラムダ式(DB向け): SQLに変換され、データベースサーバー側で実行される。
-
この「実行場所」の違いが、ラムダ式がどのように扱われるかの根本的な違いなんだ。
まとめると
| 特徴 | 普通のラムダ式 | LINQ内のラムダ式 (DB向け) |
|---|---|---|
| コンパイル後 | デリゲート (実行可能なコード) | Expression Tree (コードの構造を表すデータ) |
| 実行場所 | アプリケーションのメモリ上 | データベースサーバー上 (SQLに変換されて) |
| 変換の可否 | どんなC#コードでも書ける | SQLに変換可能なC#の構文や関数に限定される |
| 目的 | コードの簡潔化、メソッドの受け渡し | データソースへのクエリを抽象化し、SQLに変換して実行 |
だから、「普通のラムダ式」と「LINQ内のラムダ式」は、見た目は同じ=>を使っているけど、裏側では全く異なるメカニズムで動いている、というわけなんだ。
この違いを理解していると、LINQで「あれ?これなんで動かないんだろう?」となったときに、**「あ、これはSQLに変換できないパターンだな」**とすぐに気づけるようになるよ!
これで、より深く理解できたかな?