2014/01/05

[Entity Framework] SQL を直接実行する


Entity Framework は概念モデルがベースになっているので、基本は概念モデルに対して操作を行うべきなのですが、処理が複雑すぎて直接 SQL を実行せざるを得ない場合もあるかと思います。

このエントリーでは、Entity Framework で SQL を直接実行する方法をご紹介します。

前提条件

以下の前提条件で動作検証しています。

  • Visual Studio Express 2013 for Windows Desktop
  • Entity Famework 6.0.2
  • SQL Server 2012 Express
  • コンソールアプリケーション(モデルファースト、コードファースト)

Entity Framework 関連(コードファーストのみ)

商品マスタを想定して、Item クラスを作成します。

・Item.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace EFSQLDirect
{
  public class Item
  {
    public int Id { get; set; }

    public string Name { get; set; }

    public int Price { get; set;}

    [Timestamp]
    public byte[] TimeStamp { get; set; }
  }
}

データベースのテーブル定義をデータベースコンテキストで作成します。

・ItemContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace EFSQLDirect
{
  public class ItemContext:DbContext
  {
    public DbSet<Item> Items { get; set; }
  }
}

App.config にデータベースの接続文字列を設定します。接続名はコンテキストクラスと同じ必要があります。

・App.config

<connectionStrings>
  <add name="ItemContext" connectionString="Data Source=(local)\SQLEXPRESS;Initial Catalog=Item;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>

データ更新・取得プログラム

Entity Framework で SQL を直接実行する方法は2つあります。

1つは、Database.ExecuteSqlCommand メソッド を使用して、INSERT/UPDATE/DELETE といった処理を実行する方法です。ストアドプロシージャも実行可能です。また、トランザクションを内部で自動実行します(既存のトランザクションがある場合はそれを利用)。

もう1つは、Database.SqlQuery メソッド です。こちらは、SELECT 文を実行して、戻り値を通常のクラスと同じように操作できます。

なお、SQL の直接実行は、Entity Framework のバージョンによって異なるようです。ご自身が使用する Entity Framework のバージョンに注意してご利用ください。

サンプルプログラムは以下のようになります。DELETE 文実行時にトランザクションを行っています(必須ではない)。

・Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.Transactions;

namespace EFSQLDirect
{
  class Program
  {
    static void Main(string[] args)
    {
      using (var context = new ItemContext())
      {
        var item1 = new Item() { Name = "えんぴつ", Price = 100 };
        context.Items.Add(item1);

        var item2 = new Item() { Name = "けしごむ", Price = 100 };
        context.Items.Add(item2);

        var item3 = new Item() { Name = "ノート", Price = 100 };
        context.Items.Add(item3);

        context.SaveChanges();

        //SELECT 文を直接実行してデータ取得
        var items = context.Database.SqlQuery<Item>("SELECT * FROM Items;");

        foreach (var item in items)
        {
          Console.WriteLine("{0}:{1}", item.Name, item.Price);
        }

        //トランザクション開始
        using (var transaction = new TransactionScope()){

          try {
            //DELETE 文を直接実行
            int count = context.Database.ExecuteSqlCommand("DELETE FROM Items;");

            transaction.Complete();

            Console.WriteLine("{0}件削除", count);
          }
          catch (Exception)
          {
            //自動でロールバック
          }         
        }

        Console.ReadKey();
      }
    }
  }
}

コンソールに出力される実行結果は以下のようになります。期待通りで問題ありませんね。

えんぴつ:100
けしごむ:100
ノート:100
3件削除

まとめ

Entity Framework で SQL を直接実行する方法を見てきましたが、いかがだったでしょうか。適用場所を間違わなければ問題を解決する有力な手段となり得ます。

但し、最初にも書きましたが、Entity Framework の基本は概念モデルにあるので、SQL の直接実行はパフォーマンスが厳しく求められる、SQL が複雑すぎて LINQ では処理できないなどの場合に限るべきでしょう。

毎回 SQL が変わるような動的な処理の場合は、Entity SQL を採用することを検討してください。

参考サイト


スポンサーリンク


このエントリーをはてなブックマークに追加




Twitter ではブログにはない、いろんな情報を発信しています。


コメント

コメントを書く



プロフィール

  • 名前:fnya
    経歴:
    SE としての経験は15年以上。様々な言語と環境で業務系システム開発を行い、セキュリティ対策などもしていました。現在は趣味SE。

    Twitter では、ブログでは取り上げない情報も公開しています。


    ブログについて

    このブログは、IT、スマートフォン、タブレット、システム開発などに関するさまざまな話題を取り上げたり、雑感などをつづっています。


    >>ブログ詳細
    >>自作ツール
    >>運営サイト
    >>Windows 10 まとめ

    Twitter のフォローはこちらから Facebook ページはこちら Google+ページはこちら RSSフィードのご登録はこちらから