簡易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); }