程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> NHibernate之旅(20):再探SchemaExport工具使用

NHibernate之旅(20):再探SchemaExport工具使用

編輯:關於.NET

本節內容

引入

實例分析

1.表及其約束

2.存儲過程、視圖

結語

引入

上篇我們初步探索了SchemaExport工具使用,知道如何使用SchemaExport工具和SchemaUpdate工具利用NHibernate持久化類和映射文件刪除、創建、更新數據庫架構,這篇具體分析如何為表字段增加一些約束?如何生成存儲過程?如何生成視圖?使用SchemaExport工具幫你搞定。

實例分析1.表及其約束

眾所周知,SchemaExport工具根據映射文件來生成數據庫架構,在映射文件中通過Class映射可以很方便的生成數據庫表。但是這篇我們看看映射的條件,所以我重新定義兩個實體CategorySchema和ProductSchema,一對多關系。

Step1:兩個實體持久化類編寫代碼如下:

public class CategorySchema
{
  public virtual Guid Id { get; set; }
  public virtual string Name { get; set; }
}
public class ProductSchema
{
  public virtual Guid Id { get; set; }
  public virtual string Name { get; set; }
  public virtual int UnitsOnStock { get; set; }
  public virtual CategorySchema CategorySchema { get; set; }
}

Step2:為兩個實體映射,使用最簡方式,編寫代碼如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
          assembly="DomainModel" namespace="DomainModel">
 <class name="DomainModel.Entities.CategorySchema,DomainModel">
  <id name="Id">
   <generator class="guid"/>
  </id>
  <property name="Name"/>
 </class>

 <class name="DomainModel.Entities.ProductSchema,DomainModel">
  <id name="Id">
   <generator class="guid"/>
  </id>
  <property name="Name"/>
  <many-to-one name="CategorySchema"
     class="DomainModel.Entities.CategorySchema,DomainModel"/>
 </class>

</hibernate-mapping>

Step3:編寫測試用例用於生成數據庫架構:

[Test]
public void ExecuteSchemaTest()
{
  var export = new SchemaExport(_cfg);
  export.Execute(true, true, false, true);
}

Step4:測試!NHibernate生成語句如下:

if exists (select 1 from sys.objects
      where object_id = OBJECT_ID(N'[FK45BBFB51BC9515A6]')
      AND parent_object_id = OBJECT_ID('ProductSchema'))
alter table ProductSchema drop constraint FK45BBFB51BC9515A6
if exists (select * from dbo.sysobjects
      where id = object_id(N'ProductSchema')
      and OBJECTPROPERTY(id, N'IsUserTable') = 1)
  drop table ProductSchema
if exists (select * from dbo.sysobjects
      where id = object_id(N'CategorySchema')
      and OBJECTPROPERTY(id, N'IsUserTable') = 1)
  drop table CategorySchema
create table ProductSchema (
  Id UNIQUEIDENTIFIER not null,
  Name NVARCHAR(255) null,
  CategorySchema UNIQUEIDENTIFIER null,
  primary key (Id)
)
create table CategorySchema (
  Id UNIQUEIDENTIFIER not null,
  Name NVARCHAR(255) null,
  primary key (Id)
)
alter table ProductSchema add constraint FK45BBFB51BC9515A6
foreign key (CategorySchema) references CategorySchema

仔細看看生成的語句,都按默認的值生成了表,Name列字符串類型NVARCHAR(255),默認為null;外鍵默認一數字字符串等。

1.設置非空類型和長度

在映射文件中為ProductSchema實體的Name屬性添加:not-null="true"表示非空類型,length="50":列長度設置為50,代碼片段如下:

<property name="Name" not-null="true" length="50"/>

測試,生成語句如下:

create table ProductSchema (
  Id UNIQUEIDENTIFIER not null,
  Name NVARCHAR(50) not null,
  CategorySchema UNIQUEIDENTIFIER null,
  primary key (Id)
)

2.設置外鍵Foreign Keys

在映射文件設置外鍵名稱,注意有的需要兩邊都要設置才生效,代碼片段如下:

<many-to-one name="CategorySchema"
       class="DomainModel.Entities.CategorySchema,DomainModel"
       foreign-key="FK_Product_Category"/>

生成語句如下:

if exists (select 1 from sys.objects
      where object_id = OBJECT_ID(N'[FK_Product_Category]')
      AND parent_object_id = OBJECT_ID('ProductSchema'))
alter table ProductSchema drop constraint FK_Product_Category
...
alter table ProductSchema add constraint FK_Product_Category
foreign key (CategorySchema) references CategorySchema
3.設置Unique約束

我們要求Name字段唯一,添加Unique約束,代碼片段如下:

<property name="Name" not-null="true" length="50" unique="true"/>

生成語句如下:

create table ProductSchema (
  Id UNIQUEIDENTIFIER not null,
  Name NVARCHAR(50) not null unique,
  CategorySchema UNIQUEIDENTIFIER null,
  primary key (Id)
)

還有一種unique-key約束,同時為兩個屬性設置unique-key約束。我們為Customer持久化類的FirstName和LastName屬性添加Unique約束:

編寫映射,設置FirstName和LastName的Unique約束為UK_Person_Name:

<property name="FirstName" not-null="true"
     length="50" unique-key="UK_Customer_Name"/>
<property name="LastName" not-null="true"
     length="50" unique-key="UK_Customer_Name"/>

生成語句如下:

create table Customer(
  CustomerId INT IDENTITY not null,
  FirstName NVARCHAR(50) not null,
  LastName NVARCHAR(50) not null,
  primary key (CustomerId),
  unique (FirstName, LastName)
)
4.設置索引Index<property name="Name" not-null="true" length="50"
     unique="true" index="IDX_Product_Name" />

生成語句如下:

create table ProductSchema (Id UNIQUEIDENTIFIER...)
create table CategorySchema (Id UNIQUEIDENTIFIER...)
create index IDX_Product_Name on ProductSchema (Name)
5.設置Check約束

我們為UnitsOnStock值設置大於等於0:

<property name="UnitsOnStock" not-null="true" >
 <column name="UnitsOnStock" check="UnitsOnStock >= 0"/>
</property>

生成語句如下:

create table ProductSchema (
  Id UNIQUEIDENTIFIER not null,
  Name NVARCHAR(50) not null unique,
  UnitsOnStock INT null check( UnitsOnStock >= 0) ,
  CategorySchema UNIQUEIDENTIFIER null,
  primary key (Id)
)

好了,還有很多設置大家自己探索啦!知道了這些我們在寫映射的時候就注意啦!我之前映射文件屬性映射為什麼寫的比較全呢?就是這個原因,便於生成數據庫架構是自己約束的並不是默認的。

2.存儲過程、視圖

除了表,我們還有存儲過程和視圖。怎麼利用SchemaExport工具生成存儲過程和視圖呢?在映射文件中提供了database-object元素用來創建和刪除數據庫對象。

<database-object>
 <create>創建存儲過程或視圖語句等數據庫對象</create>
 <drop>刪除存儲過程或視圖語句等數據庫對象</drop>
</database-object>
1.存儲過程

還記得我們在NHibernate之旅(17):探索NHibernate中使用存儲過程(下)中創建的三個存儲過程了嗎?當時我們在數據庫中手寫創建的啊。現在完全可以不用那種古老的方法啦。我們在映射文件中編寫database-object:在創建數據庫架構時創建名為entitySProcs的存儲過程,在刪除數據庫架構時刪除名為entitySProcs的存儲過程。現在使用SchemaExport工具不僅僅生成了表,還生成了存儲過程。還剩兩個存儲過程就留給大家去完成吧。

<database-object>
  <create>
   CREATE PROCEDURE entitySProcs
   AS
   SELECT CustomerId,Version,Firstname,Lastname FROM Customer
  </create>
  <drop>
   DROP PROCEDURE entitySProcs
  </drop>
</database-object>
2.視圖

還記得我們在NHibernate之旅(14):探索NHibernate中使用視圖中創建了第一個視圖了嗎?那時我們也是在數據庫中手動創建的,現在我們可以自動創建了!打開CustomerView.hbm.xml文件,添加database-object:在創建數據庫架構時創建名為viewCustomer的視圖,在刪除數據庫架構時刪除名為viewCustomer的視圖。

<database-object>
 <create>
  CREATE VIEW [dbo].[viewCustomer]
  AS
  SELECT DISTINCT c.CustomerId, c.Firstname, c.Lastname, o.OrderId, o.OrderDate
  FROM     dbo.Customer AS c INNER JOIN
  dbo.[Order] AS o ON c.CustomerId = o.OrderId INNER JOIN
  dbo.OrderProduct AS op ON o.OrderId = op.[Order] INNER JOIN
  dbo.Product AS p ON op.Product = p.ProductId
  GROUP BY c.CustomerId, c.Firstname, c.Lastname, o.OrderId, o.OrderDate
 </create>
 <drop>drop view dbo.viewCustomer</drop>
</database-object>

測試生成數據庫架構,出現錯誤“數據庫中已存在名為'viewCustomer'的對象”。這是什麼原因呢?看看NHibernate生成語句:

create table viewCustomer (
  CustomerId INT IDENTITY NOT NULL,
  Firstname NVARCHAR(255) null,
  Lastname NVARCHAR(255) null,
  OrderId INT null,
  OrderDate DATETIME null,
  primary key (CustomerId)
)

觀察NHibernate生成SQL語句發現NHibernate利用Class映射自動生成了viewCustomer表,因為NHibernate見到Class映射就認為是表,它不知道這裡映射的是視圖,視圖和表在映射文件中沒有什麼區別。我們修改一下這個映射文件,在database-object元素上面再添加一個database-object用於刪除NHibernate生成的表。

<database-object>
 <create>drop table dbo.viewCustomer</create>
 <drop>drop table dbo.viewCustomer</drop>
</database-object>

這個database-object的意思就是在創建數據庫架構時刪除NHibernate自動生成的表viewCustomer,在刪除數據庫架構時刪除表viewCustomer。為什麼刪除兩次呢?因為我們有可能只Drop,那麼NHibernate就執行database-object中的Drop。

這樣在CustomerView.hbm.xml文件中就有兩個database-object了,總體的意思就是在創建數據庫架構時刪除NHibernate自動生成的表viewCustomer並創建名為viewCustomer的視圖,在刪除數據庫架構時刪除名為viewCustomer表和名為viewCustomer的視圖。

結語

好了,終於把SchemaExport工具研究透徹了,應該沒有說漏別的東西,就到這裡了。下面看看NHibernate對象去,什麼狀態啦,緩存啦。

出處:http://lyj.cnblogs.com

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved