Soma.Core.DbクラスのQueryOnDemandメソッド

もうひとつ紹介。
QueryOnDemandメソッドは、SQLの実行を遅延し、さらにDbDataReaderを読みながら一件一件結果を返します。大量データを扱うときに便利です。たとえば、Employeeテーブルから全件取得する次のようなコードを見てみます。

var db = new Db(new MyConfig());
var empCollection = db.QueryOnDemand<Employee>(@"select * from Employee");
var i = 0;
foreach (var e in empCollection)
{
	Console.WriteLine(e);
	i++;
	if (i == 5)
	{
		break;
	}
}

SQLが発行されるのは、遅延されてforeachで処理するときに行われます。そして、Employeeテーブルに1000件分のデータがあっても、最初の5件分しかDbDataReaderはリードされません。つまり、Employeeクラスのインスタンス化は最初の5回だけですみます。
これが、QueryOnDemandメソッドの機能です。

LINQ to SQLやEntity Frameworkではデフォルトでそのような動きになると思うのでそちらに慣れている人には驚きはないと思いますが、この機能はSomaのアピールポイントの一つです。ただ、この挙動しかないといろいろとはまりやすいので、もっとわかりやすい名前のQueryメソッドでは、メソッド実行時にSQLを発行し1000件分のEmployeeクラスのインスタンス化を即座に実行するようにしています。

ちなみに、F#からSomaを使うときはDbモジュールのqueryOnDemand関数が同じ役割を果たします。
http://soma.codeplex.com/

Soma 0.7.0.0 のC#サポートについて

Soma 0.7.0.0 で C#(やVB.NET)のサポートを強化しました。このエントリではその点について紹介します。

まず、Soma.Core.Dbの全メソッドがオーバーライド可能です。ですので、ちょっとフックしてアプリに共通の機能を入れたりと便利に使えます。
たとえば、次のコードのように更新日付は一律自動で設定するとかです。

    internal class MyDb : Db
    {
        public MyDb(IDbConfig config) : base(config)
        {
        }
        public override void Update<T>(T entity)
        {
            var prop = typeof(T).GetProperty("ModifiedDate");
            if (prop != null)
            {
                prop.SetValue(entity, DateTime.UtcNow, null);
            }
            base.Update<T>(entity);
        }
    }


それから、Soma.Core.DbはSoma.Core.IDbインタフェースを実装するようにしたので、インタフェース越しにアクセスするようにしておくと柔軟です。
たとえば、次のコードのようにファクトリで生成するとかするといいかもしれません。

    internal class DbFactory
    {
        public IDb Create()
        {
            return new MyDb(new MyConfig());
        }
    }

インタフェースがあることで状況に応じてラップしたりが簡単です。

        public IDb Wrap(IDb db)
        {
            return new Wrapper(db);
        }


どうしてもADO.NETAPIを直接触らないといけないときは、IDb.DbConfigプロパティを使ってください。
IDb.DbConfigプロパティはSoma.Core.IDbConfigインタフェースを返します、ここからはInvariantやConnectionStringが取得できます。
この2つがあればどのDBにもつなげられると思います。


Soma全体はもともとF#で使いやすいように考えましたが、Soma.Core.DbクラスやSoma.Core.IDbインタフェースについてはC#VB.NETからアクセスしやすいように作っています。C#VB.NETでも使いやすそうだなーと思ってもらえるとうれしいですね。


ちなみに、Somaのpublicなクラス・インタフェース・列挙型・例外型はすべてSoma.Core名前空間に含まれています。全部で30個くらい。このあたりも使いやすいんじゃないかと思っています!

http://soma.codeplex.com/