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

C# で使える SQL Builder を集めてみた

O/R マッパーでなくて SQL だけを作ってくれるヘルパーが欲しいなぁと思いまして(具体的には Dapper に食わせる SQL を作りたい)、SQL Builder 的なものを探してみました。O/R マッパーも混じっちゃってますが、結構見つかるもんですね。

詳細はまた後日確認するとして、備忘がてらとりあえず概要だけ。サンプルは適当に公式から引っ張ってきてるだけで動作確認してません。

Enexure.Sql.Dynamic

https://github.com/Enexure/Enexure.Sql.Dynamic/

var tableA = new Table("TableA").As("a");
var tableB = new Table("TableB").As("b");

var query = Query
    .From(tableA)
    .Join(tableB, Expression.Eq(tableA.Field("Id"), tableB.Field("Fk")))
    .Where(Expression.Eq(tableA.Field("Id"), Expression.Const(1)))
    .Select(tableA.Field("Id"), tableB.All());

Expression がちょっとあれですが、全体的に SQL そのものをイメージしやすくていいですね。

.NET Dynamic SQL Generator

http://dynasql.codeplex.com/documentation

DateTime ordersAfter = new DateTime(1990,01,01);
DBSelectQuery sel = DBQuery
    .Select()
        .Field("CustomerID")
        .Count("OrderID")
    .From("Orders")
    .GroupBy("CustomerID")
    .OrderBy("CustomerID")
    .WhereField("OrderDate", Compare.GreaterThan, DBConst.DateTime(ordersAfter));

こちらもほぼほぼ SQL 通りでいい感じですね。
色々好みはあるでしょうが、個人的に where 句は Enexure.Sql.Dynamic より好みです。
ちなみに SQL Generator って言ってますがアダプタも持ってるのでこれ一つで DB アクセスも可能です。

DbExtensions

https://github.com/maxtoroq/DbExtensions

var query = SQL
    .SELECT("ID, Name")
    .FROM("Products")
    .WHERE()
    ._If(categoryId.HasValue, "CategoryID = {0}", categoryId)
    ._If(supplierId.HasValue, "SupplierID = {0}", supplierId)
    .ORDER_BY("Name DESC"); 

Console.WriteLine(query);

今回調べた中で一番 SQL に近いライブラリ。
基本文字列ベースなので色々書けそうですし、_If メソッドはいいですね。
ちなみにアダプターも持ってます。というかアダプターに SQL Builder がくっついてる感じです。

AlchemySharp

https://github.com/FogCreek/AlchemySharp

// SQL の実行
var posts = db["Posts"];
var people = db["People"];

var results = db.Query(people["name"], posts.All())
    .From(posts)
    .Join(people.On(people["id"] == posts["author"]))
    .OrderBy(people["name"].Desc(), posts["id"])
    .Execute()
    .Select(row => new { Author = row.name, Title = row.title });

// SQL の取得(テストコードから推測)
var sql = db.Query(people["name"], posts.All())
    .From(posts)
    .Join(people.On(people["id"] == posts["author"]))
    .OrderBy(people["name"].Desc(), posts["id"])
    .SQL
    .ToSQL();

SQLAlchemy という Python の O/R マッパーにインスパイアされたらしい SQL Query Builder です。公式で Query Builder って言ってますが、普通にアダプターと一緒に使う前提ぽいです。SQL のみを取得するサンプルがありませんでしたが、軽くテストコード見た感じ、上記の通り書けば多分取れそうです。FogCreek 製ということで気になる人もいるかなーと思って載っけてみました。

Entity Framework

http://stackoverflow.com/questions/1412863/how-do-i-view-the-sql-generated-by-the-entity-framework

var result = from x in appEntities
             where x.id = 32
             select x;

var sql = ((System.Data.Objects.ObjectQuery)result).ToTraceString();

ご存じ重量級 O/R マッパーですが、実は SQL Builder としても使おうと思えば使えます。 まぁ EF を SQL Builder として使う意味は無いように思いますが、一応。

その他

調べてる過程で出てきて一応メモだけしてたもの。
SQL Builder というより、もう O/R マッパーになっちゃいますけどね。

NHibernate
https://github.com/nhibernate/nhibernate.github.io http://stackoverflow.com/questions/10704462/how-can-i-have-nhibernate-only-generate-the-sql-without-executing-it

ServiceStack.OrmLite
https://github.com/ServiceStack/ServiceStack.OrmLite http://stackoverflow.com/questions/11530943/servicestack-ormlite-sql-query-logging

C# Typed Query
http://typedquery.sourceforge.net/index.html