C#開発に欠かせないLINQとは?仕組み・環境構築・使い方を解説

LINQ
ENGINEER

C#を使ってアプリ開発を行うならば、使いこなすべき機能があります。それが「LINQ」機能です。

しかし、この「LINQ」機能、どこかとっつきにくいイメージを持っている方が多いと思います。

初学者は必ず「クエリ構文?」「メソッド構文?」「SQLと何が違うの?」といった疑問が湧いてくるはず。筆者もはじめはそうでした。

この記事では、LINQを実際に活用している筆者が基礎知識を解説します。つまづきがちなポイントをできるだけ抑えましたので、ぜひご覧ください。

C#のLINQ(統合言語クエリ)とは?

基本的にデータベースやXMLファイルなどにアプリケーション側からデータ取得や更新などを行う際には、複数の手段を使い分ける必要があります。たとえば、データベースにアクセスするためにはSQLを使用し、XMLファイルにアクセスするためにはDOMを使用するといった手法が一般的です。

しかし、この手法では対象となるデータソースが変わるたびに工数を要し、SQLなど習得すべき言語も増えてしまいます。そういった煩わしさから解放してくれるのが「LINQ」機能。LINQはデータベースやXMLファイルなど、どのデータソースにも関わらず、ひとつの統一した手法でアクセスする仕組みを提供してくれます。

また、「クエリ構文」と「メソッド構文」といった2つの構文がそれぞれ用意されているのも、LINQの大きな特徴のひとつ。

ちなみに、LINQは比較的新しい機能だと思われがちですが、じつは2007年11月リリースのC#3.0で導入された、10年以上前から活用されている技術です。

クエリ構文

SQLとコーディング方法が似ているのが「クエリ構文」です。その類似性からC#サイドでコーディングするSQLだと勘違いする方も多いのですが、実際は全くの別物になります。

SQLと似ているのは、その仕様のため。LINQはSQLに変換されてデータベース上で動作するため、使用する命令はすべてSQLに変換できる命令でなければならないのです。

var get_query = (from x in dbModel.T_URIAGE
                 where x.YEAR == "2021"
                 select new { x.PERSON_ID });

メソッド構文

「メソッド構文」ではラムダ式が採用されています。PHPやJavaでの開発経験が豊富な方は、ラムダ式のメソッド構文の方が使いやすいかもしれません。

var get_method = dbModel.T_URIAGE
                .Where(x => x.YEAR == "2021")
                .Select(x => x.PERSON_ID);

LINQ to Entitiesとは?

LINQを活用する上で、「LINQ to SQL」と「LINQ to Entities」の違いは理解しておきましょう。

「LINQ to SQL」とは、SQL Serverに対してのみ操作を行えます。それに対して「LINQ to Entities」は、OracleやMySQLなどSQL Server以外のデータベースに対して、Entity Frameworkを経由して操作できます。以下の項目では、LINQ to Entitiesの環境構築やサンプルプログラムを解説します。

Entity Frameworkの導入方法

Entity Frameworkの導入から今回は解説します。使用しているIDEは「Visual Studio Community」です。サンプルはデータベースファーストで行います。コードファーストではないのでご注意ください。

1. Entity Frameworkをインストール

NuGetを利用してEntity Frameworkをプロジェクトにインストールします。

2. ADO.NET Entity Data Modelを選択

ソリューションエクスプローラー内で右クリック→「追加」→「新しい項目」→「Data」タブ→「ADO.NET Entity Data Model」を選択します。
Entity Framework

3. 「データベースからEFDesigner」を選択

今回はデータベースファーストですので、「データベースからEFDesigner」を選択します。
Entity Framework

4. データベースの接続先を選択

今回はSQL Serverに接続します。OracleやMySQLなどでも接続できます。
Entity Framework

5. App.configに自動生成される内容を決める

「はい」を選択すれば、データベースに接続する際に必要なパスワードなどがApp.configに自動生成されます。
Entity Framework

6. 最後にテーブルを選択

アプリケーション側で操作したいテーブルを選択します。
Entity Framework

7. DbContextがプロジェクトに自動生成

自動生成されたDbContextを確認します。コーディングするのにDbContextは必要となります。

namespace WindowsFormsLINQTEST
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    
    public partial class LINQ_TEST_DBEntities : DbContext
    {
        public LINQ_TEST_DBEntities()
            : base("name=LINQ_TEST_DBEntities")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet M_PERSON { get; set; }
        public virtual DbSet T_URIAGE { get; set; }
    }
}

LINQ to Entitiesのサンプルプログラム

それでは実際に、LINQ to Entitiesを使ってサンプルプログラムを作っていきます。

使用するデータベースの内容

■T_URIAGE(トランザクション)
DB
■M_PERSON(マスタ)
DB

サンプルコーディング

  1. T_URIAGEテーブルを主テーブルとして、M_PERSONテーブルを外部結合します。
  2.  LINQ to Entities(クエリ構文)で”YEAR”項目が”2021″、”MONTH”項目が”11″のデータを抽出します。
  3. 取得したデータをループさせながら、コンソール画面に出力します。

外部結合と記載しましたが、SQLでいうところの「LEFT JOIN」はLINQにはありません。一度tempエリアにデータをため、そこからDefaultIfEmpty() 命令を使って「LEFT JOIN」のような働きをさせます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsLINQTEST
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            LINQ_TEST_DBEntities dbModel = new LINQ_TEST_DBEntities();

            try
            {
                var getqry = (from x in dbModel.T_URIAGE
                              // 外部結合
                              join y in dbModel.M_PERSON
                              on x.PERSON_ID equals y.PERSON_ID into temp
                              from z in temp.DefaultIfEmpty()
                              where x.YEAR == "2021"
                              && x.MONTH == "11"
                              select new { x, z });

                if (getqry != null)
                {
                    foreach (var item in getqry)
                    {
                        Console.WriteLine(item.x.PERSON_ID);
                        Console.WriteLine(item.z.NAME); // 結合データ
                        Console.WriteLine(item.z.ADDRESS); // 結合データ
                        Console.WriteLine(item.x.ITEM);
                        Console.WriteLine(item.x.KINGAKU);
                    }
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                dbModel.Dispose(); // 破棄は忘れずに!!
            }
        }
    }
}

出力コンソール画面の確認

PERSON_IDで結合されているので、該当するM_PERSON.NAMEとM_PERSON.ADDRESSがそれぞれ出力できていることが確認できます。
出力

LINQ to XMLを使ったXMLのデータ操作

次にLINQを使ってのXMLデータ操作を解説します。

データベースにデータを保持するほどでもないマスタデータなどは、XML形式でデータ管理することもあります。

使用するXMLファイルの内容

以下のXMLファイルをサンプル材として使用します。オーソドックスなXMLのデータ形式です。
xml

サンプルコーディング

using System.Xml.Linq;を忘れずにプログラム上部に記述しましょう。この箇所がなくてはXML操作はできません。

  1. 所定のフォルダからXMLファイルをアップロードします。
  2. LINQ to XML(クエリ構文)で”ADDRESS”項目が”TOKYO”のデータだけを抽出します。
  3. 取得したデータをループさせながら、コンソール画面に出力します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Xml.Linq;
using System.Windows.Forms;

namespace WindowsFormsLINQTEST
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                var xmlupload = @"C:\XML_INPUT\LINQTEST.xml";
                var xdocument = XDocument.Load(xmlupload);
                var getqry = (from x in xdocument.Descendants("MEIBO")
                              where x.Element("ADDRESS").Value == "TOKYO"
                              select x);

                foreach (var item in getqry)
                {
                    Console.WriteLine(item.Element("NAME").Value);
                    Console.WriteLine(item.Element("ADDRESS").Value);
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {

            }
        }
    }
}

出力コンソール画面の確認

“ADDRESS”項目が”TOKYO”のデータだけ出力できていることが確認できます。
出力

まとめ

今回はLINQについてまとめました。LINQでできることはまだまだたくさんあります。C#での開発現場では必須機能のため、早めに理解を深めておきましょう。

また、LINQ形式で統一した方が、あとから保守メンテナンスする時にも担当者が対応しやすくなります。保守・運用まで考えたコーディングができるようになれば、C#エンジニアとしてのスキルもアップすること間違いありません。
(執筆:S-KAYANO 編集:泉)

SHARE

  • 広告主募集
  • ライター・編集者募集
  • WorkshipSPACE
エンジニア副業案件
Workship