読者です 読者をやめる 読者になる 読者になる

ささいなことですが。

Windowsアプリテスト自動化ライブラリFriendly開発者の日記です。

LambdicSql - EntityFrameworkと仲良くなりました。

EntityFrameworkを使っているときでも、たまにSQLを直に書きたくなる場合がありますよね。そんな時はLambdicSqlを使うと便利です。そして、EntityFrameworkを使っている環境からLambdicSqlを使いやすい工夫を入れました。しかもそれでいてLambdicSql自体はDLL的にEntityFrameworkに依存したりはしていません。

DataContextクラスを指定できるようにしました。

EntityFrameworkでDBからモデルクラスを生成すると、こんな感じのものが生成されます。(若干省略してます)

public partial class tbl_remuneration
{
    public int? staff_id { get; set; }
    public string payment_date { get; set; }
    public int id { get; set; }
    public decimal? money { get; set; }
}

public partial class tbl_staff
{
    public int id { get; set; }
    public string name { get; set; }
}

public partial class ModelLambdicSqlTestDB : DbContext
{
    public virtual DbSet<tbl_remuneration> tbl_remuneration { get; set; }
    public virtual DbSet<tbl_staff> tbl_staff { get; set; }
}

これはLambdicSqlの定義に似ています。これをそのまま使えるようにしました。

public void TestEFAndLambdic()
{
    var query = Db<DB>.Sql(db =>
        Select(new
        {
            name = db.tbl_staff.T().name,
            payment_date = db.tbl_remuneration.T().payment_date,
            money = db.tbl_remuneration.T().money,
        }).
        From(db.tbl_remuneration.T()).
            Join(db.tbl_staff, db.tbl_remuneration.T().staff_id == db.tbl_staff.T().id);

    var datas = _connection.Query<SelectData1>(query).ToList();
}

T()がポイントですね。DbSet<>をスルーするものです。次のようなSQLになります。

SELECT
	tbl_staff.name AS "name",
	tbl_remuneration.payment_date AS "payment_date",
	tbl_remuneration.money AS "money"
FROM  tbl_remuneration
	JOIN tbl_staff ON (tbl_remuneration.staff_id) = (tbl_staff.id)

上記の例では素直にEFで書けばよいのですが、例えばOR結合を条件によって組み立てるときとか、Window関数を使うときとか、EFでは書きづらいもので利用してもらえばよいと思います。

//ORを任意の条件で組み立てるときとか
var exp = Sql<DB>.Create(db =>
    Condition(minCondition, 3000 < db.tbl_remuneration.T().money) ||
    Condition(maxCondition, db.tbl_remuneration.T().money < 4000));
var query1 = Sql<DB>.Create(db => SelectFrom(db.tbl_remuneration.T()).Where(exp));

//Window関数を使いたいときとか
var query2 = Db<DB>.Sql(db =>
    Select(new SelectData()
    {
        Average = Window.Avg(db.tbl_remuneration.T().money).
                Over<decimal>(null,
                    new OrderBy(new Asc(db.tbl_remuneration.T().payment_date)),
                    null)
    }).
    From(db.tbl_remuneration.T()));

名前解決のルールは若干違うので気を付けてください。

LambdicSqlのルールは、こちらです。EntityFrameworkとはテーブル名のルールが違っていますね。EFの場合はクラス名とテーブル名を対応させるルールで、しかも複数形と単数形の解決とか面倒なことをやってますね。とは言え、普通に生成するとEFも変数名とテーブル名は一致します。TableAttributeで指定している場合はLambdicSqlも同じルールで解決するので問題ないですね。問題ある命名している場合は、すみませんがテーブル定義を並べるクラスだけ別途作成お願いします。

是非EntityFrameworkユーザーの方もご利用お願いします!

LambdicSqlはメインでも使えて、脇役に回ってもいい仕事をするライブラリを目指しております。