使用Apworks开发基于CQRS架构的应用程序(七):配置数据库

到目前为止,我们还未涉及任何数据库的配置工作。本章节将简单介绍基于Apworks的应用程序的数据库配置。在SQL Server中(目前的Apworks版本仅支持SQL Server)创建两个数据库:TinyLibraryEventDB和TinyLibraryQueryDB,然后分别执行如下SQL脚本:

  • TinyLibraryEventDB
       1: USE TinyLibraryEventDB;
       2: /****** Object:  Table [dbo].[DomainEvents]    Script Date: 12/24/2010 20:27:20 ******/
       3: IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DomainEvents]') AND type in (N'U'))
       4: DROP TABLE [dbo].[DomainEvents]
       5: GO
       6: /****** Object:  Table [dbo].[Snapshots]    Script Date: 12/24/2010 20:27:20 ******/
       7: IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Snapshots]') AND type in (N'U'))
       8: DROP TABLE [dbo].[Snapshots]
       9: GO
      10: /****** Object:  Table [dbo].[Snapshots]    Script Date: 12/24/2010 20:27:20 ******/
      11: SET ANSI_NULLS ON
      12: GO
      13: SET QUOTED_IDENTIFIER ON
      14: GO
      15: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Snapshots]') AND type in (N'U'))
      16: BEGIN
      17: CREATE TABLE [dbo].[Snapshots](
      18:  [Id] [bigint] IDENTITY(1,1) NOT NULL,
      19:  [Timestamp] [datetime] NOT NULL,
      20:  [SnapshotData] [varbinary](max) NOT NULL,
      21:  [AggregateRootId] [bigint] NOT NULL,
      22:  [AggregateRootType] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NOT NULL,
      23:  [SnapshotType] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NOT NULL,
      24:  [Version] [bigint] NOT NULL,
      25:  [Branch] [bigint] NOT NULL,
      26:  CONSTRAINT [PK_Snapshots] PRIMARY KEY CLUSTERED 
      27: (
      28:  [Id] ASC
      29: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
      30: )
      31: END
      32: GO
      33: /****** Object:  Table [dbo].[DomainEvents]    Script Date: 12/24/2010 20:27:20 ******/
      34: SET ANSI_NULLS ON
      35: GO
      36: SET QUOTED_IDENTIFIER ON
      37: GO
      38: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DomainEvents]') AND type in (N'U'))
      39: BEGIN
      40: CREATE TABLE [dbo].[DomainEvents](
      41:  [Id] [bigint] IDENTITY(1,1) NOT NULL,
      42:  [AggregateRootId] [bigint] NOT NULL,
      43:  [AggregateRootType] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      44:  [Timestamp] [datetime] NOT NULL,
      45:  [Version] [bigint] NOT NULL,
      46:  [Branch] [bigint] NOT NULL,
      47:  [TargetType] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      48:  [Data] [varbinary](max) NOT NULL,
      49:  CONSTRAINT [PK_DomainEvents] PRIMARY KEY CLUSTERED 
      50: (
      51:  [Id] ASC
      52: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
      53: )
      54: END
      55: GO
  • TinyLibraryQueryDB
       1: USE TinyLibraryQueryDB;
       2: /****** Object:  Table [dbo].[Books]    Script Date: 12/14/2010 14:12:31 ******/
       3: IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Books]') AND type in (N'U'))
       4: DROP TABLE [dbo].[Books]
       5: GO
       6: /****** Object:  Table [dbo].[Readers]    Script Date: 12/14/2010 14:12:31 ******/
       7: IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Readers]') AND type in (N'U'))
       8: DROP TABLE [dbo].[Readers]
       9: GO
      10: /****** Object:  Table [dbo].[Registrations]    Script Date: 12/14/2010 14:12:31 ******/
      11: IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Registrations]') AND type in (N'U'))
      12: DROP TABLE [dbo].[Registrations]
      13: GO
      14: /****** Object:  Table [dbo].[Registrations]    Script Date: 12/14/2010 14:12:31 ******/
      15: SET ANSI_NULLS ON
      16: GO
      17: SET QUOTED_IDENTIFIER ON
      18: GO
      19: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Registrations]') AND type in (N'U'))
      20: BEGIN
      21: CREATE TABLE [dbo].[Registrations](
      22:  [Id] [bigint] IDENTITY(1,1) NOT NULL,
      23:  [BookId] [bigint] NOT NULL,
      24:  [ReaderId] [bigint] NOT NULL,
      25:  [ReaderName] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      26:  [ReaderLoginName] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      27:  [BookTitle] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      28:  [BookPublisher] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      29:  [BookPubDate] [datetime] NOT NULL,
      30:  [BookISBN] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      31:  [BookPages] [int] NOT NULL,
      32:  [RegistrationDate] [datetime] NULL,
      33:  [DueDate] [datetime] NULL,
      34:  [ReturnedDate] [datetime] NULL,
      35:  [Returned] [bit] NULL,
      36:  CONSTRAINT [PK_Registrations] PRIMARY KEY CLUSTERED 
      37: (
      38:  [Id] ASC
      39: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
      40: )
      41: END
      42: GO
      43: /****** Object:  Table [dbo].[Readers]    Script Date: 12/14/2010 14:12:31 ******/
      44: SET ANSI_NULLS ON
      45: GO
      46: SET QUOTED_IDENTIFIER ON
      47: GO
      48: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Readers]') AND type in (N'U'))
      49: BEGIN
      50: CREATE TABLE [dbo].[Readers](
      51:  [Id] [bigint] IDENTITY(1,1) NOT NULL,
      52:  [LoginName] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      53:  [Name] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      54:  [AggregateRootId] [bigint] NOT NULL,
      55:  CONSTRAINT [PK_Readers] PRIMARY KEY CLUSTERED 
      56: (
      57:  [Id] ASC
      58: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
      59: )
      60: END
      61: GO
      62: /****** Object:  Table [dbo].[Books]    Script Date: 12/14/2010 14:12:31 ******/
      63: SET ANSI_NULLS ON
      64: GO
      65: SET QUOTED_IDENTIFIER ON
      66: GO
      67: IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Books]') AND type in (N'U'))
      68: BEGIN
      69: CREATE TABLE [dbo].[Books](
      70:  [Id] [bigint] IDENTITY(1,1) NOT NULL,
      71:  [Title] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      72:  [Publisher] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      73:  [PubDate] [datetime] NOT NULL,
      74:  [ISBN] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      75:  [Pages] [int] NOT NULL,
      76:  [Lent] [bit] NULL,
      77:  [AggregateRootId] [bigint] NOT NULL,
      78:  [LendTo] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      79:  CONSTRAINT [PK_Books] PRIMARY KEY CLUSTERED 
      80: (
      81:  [Id] ASC
      82: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
      83: )
      84: END
      85: GO

由于我们所使用的数据库系统是SQL Server,对于上面的TinyLibraryEventDB而言,它就是直接使用的Apworks应用开发框架中自带的SQL脚本。开发人员可以在Apworks的安装目录中找到该脚本文件。

就关系型数据库而言,我们需要一个额外的步骤去维护对象与数据表的映射关系。Apworks采用的是XML Storage Mapping Schema来维护这样的关系。

  1. 向TinyLibrary.Services项目添加一个新的XML文件,将其更名为DomainEventStorageMappings.xml,然后输入下面的内容
       1: <?xml version="1.0" encoding="utf-8"?>
       2: <StorageMappingSchema>
       3:   <DataTypes>
       4:     <DataType FullName="Apworks.Events.Storage.DomainEventDataObject" MapTo="DomainEvents">
       5:       <Properties>
       6:         <Property Name="Id" MapTo="Id" Identity="true" AutoGenerate="true"/>
       7:       </Properties>
       8:     </DataType>
       9:     <DataType FullName="Apworks.Events.Storage.SnapshotDataObject" MapTo="Snapshots">
      10:       <Properties>
      11:         <Property Name="Id" MapTo="Id" Identity="true" AutoGenerate="true"/>
      12:       </Properties>
      13:     </DataType>
      14:   </DataTypes>
      15: </StorageMappingSchema>
  2. 向TinyLibrary.Services项目添加一个新的XML文件,将其更名为QueryObjectStorageMappings.xml,然后输入下面的内容
       1: <?xml version="1.0" encoding="UTF-8"?>
       2: <StorageMappingSchema>
       3:   <DataTypes>
       4:     <DataType FullName="TinyLibrary.QueryObjects.ReaderObject" MapTo="Readers">
       5:       <Properties>
       6:         <Property Name="Id" MapTo="Id" Identity="true" AutoGenerate="true"/>
       7:       </Properties>
       8:     </DataType>
       9:     <DataType FullName="TinyLibrary.QueryObjects.BookObject" MapTo="Books">
      10:       <Properties>
      11:         <Property Name="Id" MapTo="Id" Identity="true" AutoGenerate="true"/>
      12:       </Properties>
      13:     </DataType>
      14:     <DataType FullName="TinyLibrary.QueryObjects.RegistrationObject" MapTo="Registrations">
      15:       <Properties>
      16:         <Property Name="Id" MapTo="Id" Identity="true" AutoGenerate="true"/>
      17:         <Property Name="BookAggregateRootId" MapTo="BookId"/>
      18:         <Property Name="ReaderAggregateRootId" MapTo="ReaderId"/>
      19:       </Properties>
      20:     </DataType>
      21:   </DataTypes>
      22: </StorageMappingSchema>

以下是这些XML文件的XSD结构,这个XSD Schema也被包含在Apworks应用开发框架的安装目录中。

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <!-- edited with XMLSpy v2009 (http://www.altova.com) by Administrator (EMBRACE) -->
   3: <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
   4:  <xs:element name="StorageMappingSchema">
   5:   <xs:annotation>
   6:    <xs:documentation>Represents the schema for storage mapping.</xs:documentation>
   7:   </xs:annotation>
   8:   <xs:complexType>
   9:    <xs:sequence minOccurs="0">
  10:     <xs:element ref="DataTypes"/>
  11:    </xs:sequence>
  12:   </xs:complexType>
  13:  </xs:element>
  14:  <xs:element name="DataTypes">
  15:   <xs:complexType>
  16:    <xs:sequence minOccurs="0" maxOccurs="unbounded">
  17:     <xs:element ref="DataType"/>
  18:    </xs:sequence>
  19:   </xs:complexType>
  20:  </xs:element>
  21:  <xs:element name="DataType">
  22:   <xs:complexType>
  23:    <xs:sequence minOccurs="0">
  24:     <xs:element ref="Properties"/>
  25:    </xs:sequence>
  26:    <xs:attribute name="FullName" type="xs:string" use="required"/>
  27:    <xs:attribute name="MapTo" type="xs:string" use="required"/>
  28:   </xs:complexType>
  29:  </xs:element>
  30:  <xs:element name="Properties">
  31:   <xs:complexType>
  32:    <xs:sequence minOccurs="0" maxOccurs="unbounded">
  33:     <xs:element ref="Property"/>
  34:    </xs:sequence>
  35:   </xs:complexType>
  36:  </xs:element>
  37:  <xs:element name="Property">
  38:   <xs:complexType>
  39:    <xs:attribute name="Name" type="xs:string" use="required"/>
  40:    <xs:attribute name="MapTo" type="xs:string" use="required"/>
  41:    <xs:attribute name="Identity" type="xs:boolean" use="optional"/>
  42:    <xs:attribute name="AutoGenerate" type="xs:boolean" use="optional"/>
  43:   </xs:complexType>
  44:  </xs:element>
  45: </xs:schema>
posted @ 2011-02-14 16:31  dax.net  阅读(2136)  评论(0编辑  收藏  举报