EntityFramework+Azure SQL Databaseで高速な開発を実現する-LINQプログラミング編


はじめに

データを蓄積・加工する以上、個人レベルのものであっても
システムを構築するにあたってデータモデル、そしてデータベースの設計は疎かにできません。

LINQ/EntityFrameworkでは、構築したデータベースに対して、

前回投稿:EntityFramework+Azure SQL Databaseで高速なDB開発を実現する

※プログラミング編では、基盤部分にあたるAzure(SQL Database)自体への言及はほぼありません。
 データベース構築の手順・今回のデモで準備されたデータベースの詳しい内容についてはリンク先を参照してください。

前提事項

前回のデモでは、こういうエンティティ―リレーション関係にあるテーブルを作成している。
また、テーブル構造は前回のデモを引き継いでいる。

同時に自動生成されたDBContextは下記の通り。

また、前回の記事の後、EmployeeとDeptにはそれぞれ下記のようなデータを投入している。

1.単一テーブルに対するデータの取得

単一テーブルに対するSQLは、DBcontxtが持っているテーブルプロパティを取得することで生成できる。
[注意点]
・必ずusingを利用してリソースを閉じる(リソース・リーク防止)
・usingを抜ける前の段階で終端処理を終えておき、IEnumerableのままにしない(クエリを確定させる)

Statistics.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using WebApplication6.Model;

    public class Statistics {

        public static List<Dept> getDept() {
            //必ずusingブロックで囲い、DBリソースは破棄する
            using (var db = new EFTestModelContainer()) {
                return db.DeptSet.ToList();
            }
        }

/**
[DB取得結果]
1,総務
2,システム
3,経理

[生成SQL]
SELECT 
    [Extent1].[DeptId] AS [DeptId], 
    [Extent1].[DeptName] AS [DeptName]
    FROM [dbo].[DeptSet] AS [Extent1]
*/

2.外部キーによるテーブルの結合(内部結合)

Where等のために結合させるケースでは、
親エンティティを取得する→親エンティティが持っている子エンティティのセットを取得してさらに処理する。

[注意点]
・結合時、Join方法を正確に指定することができない。したがって効率の悪いSQL発行となる場合がある。
・サンプルでは無視しているが、例外の発生を考慮すること。

Statistics.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using WebApplication6.Model;

    public class Statistics {

        public static double AverageSalary(String DeptName) {
            using (var db = new EFTestModelContainer()) {
                return db.DeptSet.Where(d => d.DeptName.Equals(DeptName)).SelectMany(d => d.Employee).Average(e => e.Salary);
            }
        }

/**
[処理]
従業員が所属する部門が 総務 である従業員の 給与平均 を算出する。

[DB取得結果]
300000

[生成SQL]
exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        AVG( CAST( [Extent2].[Salary] AS float)) AS [A1]
        FROM  [dbo].[DeptSet] AS [Extent1]
        INNER JOIN [dbo].[EmployeeSet] AS [Extent2] ON [Extent1].[DeptId] = [Extent2].[Dept_DeptId]
        WHERE [Extent1].[DeptName] = @p__linq__0
    )  AS [GroupBy1]',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'総務'
*/