Web Service Software Factory
ソフトウエア・ファクトリの具体例として出てきているもので、Webサービス+データアクセスのコード生成が出来るようになっています。
以前、評価しようとしてインストールしていたのだが、仕組みのGAT(Guidance Automation Toolkit)の方が気になり、DEEPな世界に足を踏み入れ挫折していました。たまたま、少し動かしてみると、案外面白そうなのでメモがてら紹介しておきます。ウイザード画面と生成されるコードが一番イメージが伝わるかな。
データアクセス
テーブルを指定すると単純なCRUDのストプロのコードを生成してくれます。
ALTER PROCEDURE [dbo].[InsertCategories] @categoryID int OUT, @categoryName nvarchar(15), @description ntext = NULL, @picture image = NULL AS BEGIN SET NOCOUNT ON BEGIN TRY INSERT INTO [dbo].[Categories] ([CategoryName], [Description], [Picture]) VALUES (@categoryName, @description, @picture) SET @categoryID = SCOPE_IDENTITY() END TRY BEGIN CATCH EXEC RethrowError; END CATCH SET NOCOUNT OFF END GO IF NOT EXISTS (SELECT NAME FROM sys.objects WHERE TYPE = 'P' AND NAME = 'UpdateCategories') BEGIN EXEC('CREATE PROCEDURE [dbo].[UpdateCategories] AS RETURN') END GO ALTER PROCEDURE [dbo].[UpdateCategories] @categoryID int, @categoryName nvarchar(15), @description ntext = NULL, @picture image = NULL AS BEGIN --The [dbo].[Categories] table doesn't have a timestamp column. Optimistic concurrency logic cannot be generated SET NOCOUNT ON BEGIN TRY UPDATE [dbo].[Categories] SET [CategoryName] = @categoryName, [Description] = @description, [Picture] = @picture WHERE [CategoryID]=@categoryID IF @@ROWCOUNT = 0 BEGIN RAISERROR('Concurrent update error. Updated aborted.', 16, 2) END END TRY BEGIN CATCH EXEC RethrowError; END CATCH SET NOCOUNT OFF END GO IF NOT EXISTS (SELECT NAME FROM sys.objects WHERE TYPE = 'P' AND NAME = 'DeleteCategories') BEGIN EXEC('CREATE PROCEDURE [dbo].[DeleteCategories] AS RETURN') END GO ALTER PROCEDURE [dbo].[DeleteCategories] @categoryID int AS BEGIN SET NOCOUNT ON DELETE FROM [dbo].[Categories] WHERE [CategoryID]=@categoryID SET NOCOUNT OFF END GO IF NOT EXISTS (SELECT NAME FROM sys.objects WHERE TYPE = 'P' AND NAME = 'GetAllFromCategories') BEGIN EXEC('CREATE PROCEDURE [dbo].[GetAllFromCategories] AS RETURN') END GO ALTER PROCEDURE [dbo].[GetAllFromCategories] AS BEGIN SET NOCOUNT ON SELECT [categories].[CategoryID] AS 'CategoryID', [categories].[CategoryName] AS 'CategoryName', [categories].[Description] AS 'Description', [categories].[Picture] AS 'Picture' FROM [dbo].[Categories] [categories] SET NOCOUNT OFF END GO IF NOT EXISTS (SELECT NAME FROM sys.objects WHERE TYPE = 'P' AND NAME = 'GetCategoriesByCategoryID') BEGIN EXEC('CREATE PROCEDURE [dbo].[GetCategoriesByCategoryID] AS RETURN') END GO ALTER PROCEDURE [dbo].[GetCategoriesByCategoryID] @categoryID int AS BEGIN SET NOCOUNT ON SELECT [categories].[CategoryID] AS 'CategoryID', [categories].[CategoryName] AS 'CategoryName', [categories].[Description] AS 'Description', [categories].[Picture] AS 'Picture' FROM [dbo].[Categories] [categories] WHERE [CategoryID]=@categoryID SET NOCOUNT OFF END GO
ビジネスエンティティの生成
テーブルを指定するとエンティティクラスを生成してくれます。型指定されたDataSetじゃ無く、POCO(素のクラス)を生成します。
public partial class Region { public Region() { } public Region(System.String regionDescription, System.Int32 regionID) { this.regionDescriptionField = regionDescription; this.regionIDField = regionID; } private System.String regionDescriptionField; public System.String RegionDescription { get { return this.regionDescriptionField; } set { this.regionDescriptionField = value; } } private System.Int32 regionIDField; public System.Int32 RegionID { get { return this.regionIDField; } set { this.regionIDField = value; } } }
サービススキーマの定義
Webサービスで受け渡すスキーマ構造を定義します。早い話がDTOみたいなものです。
[System.SerializableAttribute()] [System.Xml.Serialization.XmlRootAttribute( Namespace = "http://ASMXService1.DataTypes/2006/11", IsNullable = false)] public class Product { private string productID; private string productName; public string ProductID { get { return this.productID; } set { this.productID = value; } } public string ProductName { get { return this.productName; } set { this.productName = value; } } }
ビジネスエンティティとサービススキーマの変換処理
サービス指向にクラスを公開するのではなくスキーマを公開するという考え方があります。このため、外部向けのサービススキーマと内部のビジネスエンティティの2つのデータ構造が作成されます。この変換を行う処理を生成できるようにしているようです。
public class TranslateBetweenSampleDataAndCustomers { public ASMXService1.BusinessEntities.Customers TranslateSampleDataToCustomers (ASMXService1.DataTypes.SampleData from) { ASMXService1.BusinessEntities.Customers to = new ASMXService1.BusinessEntities.Customers(); to.Address = from.Address; to.City = from.City; to.CompanyName = from.CompanyName; to.ContactName = from.ContactName; to.ContactTitle = from.ContactTitle; to.Country = from.Country; to.CustomerID = from.CustomerID; to.Fax = from.Fax; to.Phone = from.Phone; to.PostalCode = from.PostalCode; to.Region = from.Region; return to; } public ASMXService1.DataTypes.SampleData TranslateCustomersToSampleData (ASMXService1.BusinessEntities.Customers from) { ASMXService1.DataTypes.SampleData to = new ASMXService1.DataTypes.SampleData(); to.Address = from.Address; to.City = from.City; to.CompanyName = from.CompanyName; to.ContactName = from.ContactName; to.ContactTitle = from.ContactTitle; to.Country = from.Country; to.CustomerID = from.CustomerID; to.Fax = from.Fax; to.Phone = from.Phone; to.PostalCode = from.PostalCode; to.Region = from.Region; return to; } }