簡易ORMフレームワークを作成してみる(3)
等号フィルタの作成
基本的な構造が出来上がったのであとはバリエーションを増やしていくだけです。
まずは、最初のシナリオを実現するための等号フィルタの作成に取り掛かります。
EqCriteriaみたいな等号フィルタを作ることももちろん可能できすが、同じようなパターンで等号以外にも以上、以下などの多くのバリエーションがあることが予想できますので、もう少し一般化したFilterCriteriaを作成し、等号フィルタをインスタンスとして表現できるようにします。FilterCriteriaはSQL文の雛形になるExpressionと、カラム名、パラメータを情報として持たせるようにします。
雛形はString.Formatの形式で表現するのが簡単です。第1引数がカラム名、それ以降がパラメータの引数になるようにします。たとえば、等号フィルタの雛形は、"{0} = {1}"となり、生成される検索文は"カラム名 = @p1"のようになります。
[Serializable] public class FilterCriteria : Criteria { private string _expression; public string Expression { get { return _expression; } set { _expression = value; } } private object _parameters; public object Parameters { get { return _parameters; } set { _parameters = value; } } private string _columnName; public string ColumnName { get { return _columnName; } set { _columnName = value; } } public FilterCriteria() { } public FilterCriteria(string expression, string columnName) { this.Expression = expression; this.ColumnName = columnName; this.Parameters = null; } public FilterCriteria(string expression, string columnName, params object[] parameters) { this.Expression = expression; this.ColumnName = columnName; this.Parameters = parameters; } public override string GenerateQueryStatement(QueryObjectBuilder builder) { return builder.GenerateFilterCriteria(this); } }
SQL文の検索条件の生成については、カラム名の表現がRDBMSに依存する点もあり、QueryObjectBuilderに一任するようにします。したがって、QueryObjectBuilderにそのためのメソッドを追加します。Criteriaの具象クラスでRDBMSに依存するようなものがあれば、このパターンでQueryObjectBuilderにメソッドを追加するようになります。
public abstract class QueryObjectBuilder { ... //個別の検索フィルタから特定のRDBMSで利用可能な検索文を生成する public virtual string GenerateFilterCriteria(FilterCriteria item) { } }
ここまできたら、あとはFilterCriteriaを利用して等号フィルタを作成すればOKです。この生成の責務はCriteriaを集約しているQueryObjectに持たせると良さそうなのでファクトリのメソッドを追加することにします。ついでに、便利なサブのメソッドも追加しておきます。
[Serializable] public class QueryObject { ... public FilterCriteria CreateFilter(string columnName, string expression, params object[] parameters) { return new FilterCriteria(expression, columnName, parameters); } public FilterCriteria CreateOperatorFilter(string columnName, string ope, object value) { return new FilterCriteria("{0} " + ope + " {1}", columnName, value); } public FilterCriteria Eq(string columnName, object value) { return CreateOperatorFilter(columnName, "=", value); } }