簡易ORMフレームワークを作成してみる(10)

SQL文自動生成

型指定されたDataSetからSQL文の作成する際のポイントは、個別のDBMSの機能をどのようにして外だしするかです。今回はDbProviderAdapterでカラムやテーブル名のスケープ処理やRDBMS固有の関数名を隠居しています。微妙な違いはサブクラス化しなくてもこの方式で対応できコードの共通化も進みます。ただ、ID自動採番の仕組みの違いような処理方式に影響する内容はサブクラスで対応することになります。
あとはひたすらSQL文を組み立てるだけです。

public abstract class DataCommandBuilder
{
	...
	
	public virtual DbCommand GetInsertCommand(DataTable schema)
	{
		DbCommand cmd = Adapter.CreateCommand();
		List insertColumns = GetInsertColumn(schema);
	
		string parameterOptionStatement = string.Empty;
		string valueOptionStatement = string.Empty;
		if (HasLockVersionColumn(schema))
		{
			parameterOptionStatement = "," +
			 GetColumnExpression(schema.Columns[Config.VersionColumnName]);
			valueOptionStatement = ",0";
			insertColumns.Remove(schema.Columns[Config.VersionColumnName]);
		}
	
		if (HasCreatedAtColumn(schema))
		{
			parameterOptionStatement += "," +
			 GetColumnExpression(schema.Columns[Config.CreatedAtColumnName]);
			valueOptionStatement += "," +
			 Adapter.GetDbmsFunction(DbmsFunction.GetDate);
			insertColumns.Remove(schema.Columns[Config.CreatedAtColumnName]);
		}
	
		if (HasUpdatedAtColumn(schema))
		{
			insertColumns.Remove(schema.Columns[Config.UpdatedAtColumnName]);
		}
	
		cmd.CommandText = String.Format(
			"Insert Into {0} ({1}{2}) Values ({3}{4})",
			GetTableExpression(schema),
			string.Join(",", 
				insertColumns.ConvertAll(
					GetColumnExpression).ToArray()),
			parameterOptionStatement,
			string.Join(",",
				insertColumns.ConvertAll(
					GetColumnParameter).ToArray()),
			valueOptionStatement
			);
	
		cmd.Parameters.AddRange(
			insertColumns.ConvertAll(
				Adapter.CreateParameter).ToArray());
		return cmd;
	}

	protected virtual List GetInsertColumn(DataTable schema)
	{
		List columns = new List();
		foreach (DataColumn column in schema.Columns)
		{
			if (!column.ReadOnly || !column.AutoIncrement)
			{
				columns.Add(column);
			}
		}
		return columns;
	}
}

public class SqlDataCommandBuilder : DataCommandBuilder
{
	protected override DbProviderAdapter Adapter
	{
		get { return new SqlDbProviderAdapter(); }
	}

	protected override QueryObjectBuilder CreateQueryObjectBuilder(QueryObject query)
	{
		return new SqlQueryObjectBuilder(query);
	}

	public override DbCommand GetInsertCommand(DataTable schema)
	{
		DbCommand cmd = base.GetInsertCommand(schema); 
		if (schema.PrimaryKey != null &&
			schema.PrimaryKey.Length == 1 && schema.PrimaryKey[0].AutoIncrement)
		{
			DataColumn pkColumn = schema.PrimaryKey[0];
			List columns = GetSelectColumn(schema);
			cmd.CommandText += string.Format(
				";Select {0} From {1} Where ({2}=SCOPE_IDENTITY())",
				GetColumnExpression(pkColumn),
				GetTableExpression(schema),
				GetColumnExpression(pkColumn));
	
		}
		return cmd;
	}

}