Entity Framework Core SQL文の利用

 Entity FrameworkでSQL文は使えないの?と思われるかもしれませんが、ちゃんと使えます。ただ、これもポイントがあって色々ハマったので書いておきます。JOINしてデータを取得したいときはLINQを使って取得するのが望ましいらしいんですが、それでもいいんですが、やはりSQLでSelect文を使いたい時ってないですか?Select文のいいところって、動的に条件文を組み立てる事が出来るので便利なんですよ。個人的にはSQL文って素晴らしい技術だと思っていますが、なんでEntity Frameworkはそれを活かしてくれていない設計にしたんだと思ったりします。いや、すごい便利なんですけどね。DBのカラムを1つ追加するだけで、まずTableのCreate文、モデルクラス、Insert文、Select文と直すところが一杯あって、とにかく面倒くさいんですが、その工程を見事に減らしてくれてますもんね。因みにLINQで動的に条件文を作成するやり方は、こちらのページが参考になりましたが、もっと複雑な条件文を作りたい時とかです。

C# linqで動的なWhere句を生成する方法 | ITエンジニア考察雑記 (tomisenblog.com)

前置きが長くなりましたが、まずはUpdate文を使ってみます。変更ボタンを押下すると本の名前の前にVIP-と付けるUpdate文を実行するには以下のようなコードを記述します。

 private void buttonUpdate_Click(object sender, EventArgs e)
 {
     var lists = _dbContext.Books.ToList();
     if (lists.Count == 0)
         return;

     string whereStr = "where BookID IN (";
     foreach (var table in lists)
     {
         whereStr = whereStr + table.BookID + ",";
     }

     whereStr = whereStr.Substring(0, whereStr.Length - 1);
     whereStr = whereStr + ")";

     var sql = @"UPDATE Book set BookName = 'VIP-' + BookName " + whereStr;
     System.FormattableString fstr1 = FormattableStringFactory.Create(sql);

     _dbContext.Database.ExecuteSql(fstr1);
 }

まず、アプリを起動して、データを読み込みます。

変更を押下して上記のUPDATE文を実行します。しかし、もう一度データ読込ボタンを押下しても更新した内容が反映されません。これは、直接SQL文を実行すると、EFの追跡機能からは外れる為、DBContextで再度データを取得しても変わらないそうです。

Book2の方はAsNoTrackingでデータを取得しているので、常に最新の情報が持ってこれます。じゃあ、AsNoTrackingで取得したほうがいいの?といえばそうでもないみたいです。AsNoTrackingと書くと追跡機能から外れるので、Updateする時に、EFが何処が変更されているか常に追跡しているので「_dbContext.SaveChanges();」と書くだけでOKですが、これが使えなくなります。データ量、使い方、取得の仕方、どのようなシステムであるかを考慮してコーディングしていく必要がありそうですね。

では、JoinしたSelect文を実行するにはどのようにするかというと、Viewテーブルを作成してDBContextクラスに追加します。

public class ViewBook2
{
    [Key]
    public int Book2ID { get; set; }

    [StringLength(100)]
    public string BookName { get; set; } = string.Empty;

    public int CategoryID { get; set; }

    public string CategoryName { get; set; } = string.Empty;
}

以下のように、記述すればViewクラスに値が設定されます。

string sql = "SELECT a.Book2ID, a.BookName, a.CategoryID, b.CategoryName from Book2 a, BookCategory b where a.CategoryID = b.CategoryID";
var datas = _dbContext.ViewBook2s.FromSqlRaw(sql).ToList();

ただ、これはコードファーストでテーブルを作成する時に、こちらのテーブルが作成されてしまいますので、テーブルを作成する時はコメントアウトにしておくしかないのでしょうか?こちらはちょっとまだいいやり方があるのか不明です。

Follow me!

コメントする

PAGE TOP