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

SQL文自動生成

前回の続きで、型指定されたDataSetの情報からSQL文を作成するクラスライブラリについて整理していきます。まずは、全体のクラス構成から見てみましょう。SQL文の生成の中心的なクラスはDataCommandBuilderクラスです。GetSelectCommandやGetDeleteCommandなどSQL文を生成するメソッドを持っています。派生クラスとしてSQL Server用のSqlDataCommandBuilderを今回は用意しています。その他のRDBMSも同様にDataCommandBuilderから派生して作成することになります。
関連クラスとしては、DataCommandBuilderConfigクラスがあります。これは、SQL文を作成するときの構成情報、たとえば、楽観ロック用のカラムやレコード更新カラムなどの情報を持っています。あとは、個別RDBMSインスタンス生成やDBMS関数の情報提供してもらうためのDbProviderAdapterと協調します。


今回目標にするシナリオは、型指定されたDataSetからSQL文を生成するところまでになります。


[Test]
public void 全件SELECT文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetSelectCommand(new ShippersDataSet().Shippers, null);
	Assert.AreEqual(
	  "Select [ShipperID],[CompanyName],[Phone] From [Shippers]", c.CommandText);
}

[Test]
public void SELECT文検索条件付()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	QueryObject q = new QueryObject();
	q.Filter = q.Eq("ShipperID", 1);
	DbCommand c = b.GetSelectCommand(new ShippersDataSet().Shippers, q);
	Assert.AreEqual(
	  "Select [ShipperID],[CompanyName],[Phone] From [Shippers] Where [ShipperID] = @p1",
	  c.CommandText);
	Assert.AreEqual(1,c.Parameters[0].Value);
}

[Test]
public void Count検索条件付()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	QueryObject q = new QueryObject();
	q.Filter = q.Eq("ShipperID", 1);
	DbCommand c = b.GetCountCommand(new ShippersDataSet().Shippers, q);
	Assert.AreEqual(
	  "Select count(*) From [Shippers] Where [ShipperID] = @p1", c.CommandText);
	Assert.AreEqual(1, c.Parameters[0].Value);
}

[Test]
public void UPDATE文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetUpdateCommand(new ShippersDataSet().Shippers);
	Assert.AreEqual("Update [Shippers] Set [CompanyName]=@CompanyName,[Phone]=@Phone
 Where [ShipperID]=@ShipperID", c.CommandText);
	Assert.AreEqual(3, c.Parameters.Count);
	Assert.AreEqual("@CompanyName", c.Parameters[0].ParameterName);
	Assert.AreEqual("@Phone", c.Parameters[1].ParameterName);
	Assert.AreEqual("@ShipperID", c.Parameters[2].ParameterName);
}

[Test]
public void 楽観ロックUpdatedAt付UPDATE文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetUpdateCommand(new TestCommandBuilderDataSet().BuilderTable);
	Assert.AreEqual(
	  "Update [BuilderTable] Set [Column1]=@Column1,[Column2]=@Column2,[Column3]=@Column3,
[LockVersion]=[LockVersion]+1,[UpdatedAt]=GETDATE() Where [ID]=@ID And [LockVersion]=@LockVersion",
	  c.CommandText);
	Assert.AreEqual(5, c.Parameters.Count);
}

[Test]
public void INSERT文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetInsertCommand(new ShippersDataSet().Shippers);
	Assert.IsTrue(c.CommandText.StartsWith("Insert Into [Shippers] ([CompanyName],[Phone])
 Values (@CompanyName,@Phone)"));
	Assert.AreEqual(2, c.Parameters.Count);
	Assert.AreEqual("@CompanyName", c.Parameters[0].ParameterName);
	Assert.AreEqual("@Phone", c.Parameters[1].ParameterName);
}

[Test]
public void CreatedAt付INSERT文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetInsertCommand(new TestCommandBuilderDataSet().BuilderTable);
	Assert.AreEqual("Insert Into [BuilderTable] ([ID],[Column1],[Column2],[Column3],
[LockVersion],[CreatedAt]) Values (@ID,@Column1,@Column2,@Column3,0,GETDATE())", c.CommandText);
	Assert.AreEqual(4, c.Parameters.Count);
}

[Test]
public void DELETE文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetDeleteCommand(new ShippersDataSet().Shippers);
	Assert.AreEqual("Delete From [Shippers] Where [ShipperID]=@ShipperID", c.CommandText);
	Assert.AreEqual(1, c.Parameters.Count);
	Assert.AreEqual("@ShipperID", c.Parameters[0].ParameterName);
}

[Test]
public void LockVersion付DELETE文()
{
	DataCommandBuilder b = new SqlDataCommandBuilder();
	DbCommand c = b.GetDeleteCommand(new TestCommandBuilderDataSet().BuilderTable);
	Assert.AreEqual(
	  "Delete From [BuilderTable] Where [ID]=@ID And [LockVersion]=@LockVersion", c.CommandText);
	Assert.AreEqual(2, c.Parameters.Count);
}