目錄
寫在前面
文檔與系列文章
SchemaExport工具
SchemaUpdate工具
一個例子
總結
上篇文章介紹了使用代碼生成器的nhibernate模版來生成持久化類,映射檔案等内容。本篇文章将繼續介紹工具SchemaExport和SchemaUpdate。說實話,這東西我也是第一次使用,也隻能邊摸索,邊學習了。
一般的開發模式是先将資料庫架構設計好,然後再編寫持久化類和映射檔案,也就是資料庫驅動的模式。然而也可以先編寫持久化類和映射檔案,然後通過SchemaExport工具生成資料庫架構。通過面向對象的思想,來生成對應的資料庫架構,似乎是更合理的(個人觀點)。
這種先編寫持久化類和映射檔案在生成資料庫架構有什麼好處呢?
如果在設計的時候,我們的領域模型需要改變,隻需修改NHibernate結構和應用程式,不需要修改資料庫架構,隻要利用SchemaExport工具重新生成資料庫架構就可以了。
[Nhibernate]體系結構
[NHibernate]ISessionFactory配置
[NHibernate]持久化類(Persistent Classes)
[NHibernate]O/R Mapping基礎
[NHibernate]集合類(Collections)映射
[NHibernate]關聯映射
[NHibernate]Parent/Child
[NHibernate]緩存(NHibernate.Caches)
[NHibernate]NHibernate.Tool.hbm2net
[NHibernate]Nullables
[NHibernate]Nhibernate如何映射sqlserver中image字段
[NHibernate]基本配置與測試
[NHibernate]HQL查詢
[NHibernate]條件查詢Criteria Query
[NHibernate]增删改操作
[NHibernate]事務
[NHibernate]并發控制
[NHibernate]元件之依賴對象
[NHibernate]一對多關系(級聯删除,級聯添加)
[NHibernate]一對多關系(關聯查詢)
[NHibernate]多對多關系(關聯查詢)
[NHibernate]延遲加載
[NHibernate]立即加載
[NHibernate]視圖處理
[NHibernate]N+1 Select查詢問題分析
[NHibernate]存儲過程的使用(一)
[NHibernate]存儲過程的使用(二)
[NHibernate]存儲過程的使用(三)
NHibernate的hbm2dll提供SchemaExport工具:給定一個連接配接字元串和映射檔案,不需輸入其他東西就可以按照持久化類和映射檔案自動生成資料庫架構,現在SchemaExport工具還不是很強大,但是一般應用足夠了,它還是一個相當原始的API還在不斷改進。
SchemaExport工具就是把DDL腳本輸出到标準輸出,同時/或者執行DDL語句。SchemaExport工具提供了三個方法,分别是Drop()、Create()、Execute(),前兩個方法實質是調用Execute()方法。通常使用Execute()方法來生成資料庫架構的。
在NHibernate2.0中新添加SchemaUpdate工具,可以用來更新資料庫架構。但是我覺得沒有什麼作用,因為它不能Drop現有的表或列,也不能更新現有的列,隻能添加新的表和列。如果我需要删除表或者列或者修改其中列,SchemaUpdate工具就顯得無能為力了。
現在資料通路測試層建立一SchemaExportFixture.cs檔案用于測試。
1 /// <summary>
2 /// 描述:SchemaExport生成資料庫架構操作類
3 /// 建立人:wolfy
4 /// 建立時間:2014-11-16
5 /// </summary>
6 public class SchemaExportFixture
7 {
8 private Configuration _cfg;
9 public SchemaExportFixture()
10 {
11 _cfg = new Configuration();
12 _cfg.Configure();
13 }
14 public void DropTest()
15 {
16 var export = new SchemaExport(_cfg);
17 export.Drop(true, true);
18 }
19 public void CreateTest()
20 {
21 var export = new SchemaExport(_cfg);
22 export.Create(true, true);
23 }
24 public void ExecuteTest()
25 {
26 var export = new SchemaExport(_cfg);
27 export.Execute(true, true, false);
28 }
29 }
需要引入命名空間
測試Drop方法
方法描述
Drop(script, export)方法根據持久類和映射檔案執行删除資料庫架構。有兩個參數,第一個為True就是把DDL語句輸出到控制台,第二個為True就是根據持久類和映射檔案執行删除資料庫架構操作,經過調試可以發現Drop(script, export)方法其實質是執行了Execute(script, export, true, true)方法。
1 //
2 // 摘要:
3 // Run the schema creation script
4 //
5 // 參數:
6 // exportOutput:
7 // if non-null, the ddl will be written to this TextWriter.
8 //
9 // execute:
10 // true if the ddl should be executed against the Database.
11 //
12 // 備注:
13 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Boolean,System.Boolean,System.Boolean)
14 // and sets the justDrop parameter to false.
15 public void Create(TextWriter exportOutput, bool execute);
16 //
17 // 摘要:
18 // Run the drop schema script
19 //
20 // 參數:
21 // useStdOut:
22 // true if the ddl should be outputted in the Console.
23 //
24 // execute:
25 // true if the ddl should be executed against the Database.
26 //
27 // 備注:
28 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Boolean,System.Boolean,System.Boolean)
29 // and sets the justDrop parameter to true.
30 public void Drop(bool useStdOut, bool execute);
31 //
32 // 摘要:
33 // Run the drop schema script
34 //
35 // 參數:
36 // exportOutput:
37 // if non-null, the ddl will be written to this TextWriter.
38 //
39 // execute:
40 // true if the ddl should be executed against the Database.
41 //
42 // 備注:
43 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Action<System.String>,System.Boolean,System.Boolean,System.IO.TextWriter)
44 // and sets the justDrop parameter to true.
45 public void Drop(TextWriter exportOutput, bool execute);
Drop
1 public void DropTest()
2 {
3 var export = new SchemaExport(_cfg);
4 export.Drop(true, true);
5 }
生成的sql語句
測試Create方法
Create(script,export)方法根據持久類和映射檔案先删除架構後建立删除資料庫架構。有兩個參數,第一個為True就是把DDL語句輸出到控制台,第二個為True就是根據持久類和映射檔案先執行删除再執行建立操作,經過調試可以發現這個方法其實質是執行Execute(script,export, false, true)方法。
1 // 摘要:
2 // Run the schema creation script
3 //
4 // 參數:
5 // scriptAction:
6 // an action that will be called for each line of the generated ddl.
7 //
8 // execute:
9 // true if the ddl should be executed against the Database.
10 //
11 // 備注:
12 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Boolean,System.Boolean,System.Boolean)
13 // and sets the justDrop parameter to false.
14 public void Create(Action<string> scriptAction, bool execute);
15 //
16 // 摘要:
17 // Run the schema creation script
18 //
19 // 參數:
20 // useStdOut:
21 // true if the ddl should be outputted in the Console.
22 //
23 // execute:
24 // true if the ddl should be executed against the Database.
25 //
26 // 備注:
27 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Boolean,System.Boolean,System.Boolean)
28 // and sets the justDrop parameter to false.
29 public void Create(bool useStdOut, bool execute);
30 //
31 // 摘要:
32 // Run the schema creation script
33 //
34 // 參數:
35 // exportOutput:
36 // if non-null, the ddl will be written to this TextWriter.
37 //
38 // execute:
39 // true if the ddl should be executed against the Database.
40 //
41 // 備注:
42 // This is a convenience method that calls NHibernate.Tool.hbm2ddl.SchemaExport.Execute(System.Boolean,System.Boolean,System.Boolean)
43 // and sets the justDrop parameter to false.
44 public void Create(TextWriter exportOutput, bool execute);
Create
1 public void CreateTest()
2 {
3 var export = new SchemaExport(_cfg);
4 export.Create(true, true);
5 }
通過最後一條你也會發現,連視圖也生成了。
測試Execute方法
Execute(script, export, justDrop)方法根據持久類和映射檔案先删除架構後再建立删除資料庫架構。(nhibernate4.0中已經将第四個參數format去掉了)
有三個參數,第一個為True就是把DDL語句輸出到控制台;
第二個為True就是根據持久類和映射檔案在資料庫中先執行删除再執行建立操作;
第三個為false表示不是僅僅執行Drop語句還執行建立操作,這個參數的不同就擴充了上面兩個方法;
1 public void Execute(Action<string> scriptAction, bool execute, bool justDrop);
2 //
3 // 摘要:
4 // Executes the Export of the Schema.
5 //
6 // 參數:
7 // useStdOut:
8 // true if the ddl should be outputted in the Console.
9 //
10 // execute:
11 // true if the ddl should be executed against the Database.
12 //
13 // justDrop:
14 // true if only the ddl to drop the Database objects should be executed.
15 //
16 // 備注:
17 // This method allows for both the drop and create ddl script to be executed.
18 public void Execute(bool useStdOut, bool execute, bool justDrop);
19 public void Execute(Action<string> scriptAction, bool execute, bool justDrop, TextWriter exportOutput);
20 public void Execute(Action<string> scriptAction, bool execute, bool justDrop, IDbConnection connection, TextWriter exportOutput);
21 //
22 // 摘要:
23 // Executes the Export of the Schema in the given connection
24 //
25 // 參數:
26 // useStdOut:
27 // true if the ddl should be outputted in the Console.
28 //
29 // execute:
30 // true if the ddl should be executed against the Database.
31 //
32 // justDrop:
33 // true if only the ddl to drop the Database objects should be executed.
34 //
35 // connection:
36 // The connection to use when executing the commands when export is true. Must
37 // be an opened connection. The method doesn't close the connection.
38 //
39 // exportOutput:
40 // The writer used to output the generated schema
41 //
42 // 備注:
43 // This method allows for both the drop and create ddl script to be executed.
44 // This overload is provided mainly to enable use of in memory databases. It
45 // does NOT close the given connection!
46 public void Execute(bool useStdOut, bool execute, bool justDrop, IDbConnection connection, TextWriter exportOutput);
Execute
1 public void ExecuteTest()
2 {
3 var export = new SchemaExport(_cfg);
4 export.Execute(true, true, false);
5 }
通過比較你會發現Execute和Create生成的sql語句很相似
測試Execute(Action<string> scriptAction, bool execute, bool justDrop, TextWriter exportOutput)方法
根據持久類和映射檔案先删除架構後建立删除資料庫架構。有四個參數。
第一個為一個帶一個字元串類型輸入參數的委托方法。
第二個為true表示對資料庫執行DDL。
第三個為true表示如果隻有DDL删除資料庫對象應該被執行。
第四個為一個TextWriter輸出到一個TextWriter中。
1 public void ExecuteOutTest()
2 {
3 var export = new SchemaExport(_cfg);
4 StringBuilder sb=new StringBuilder();
5 TextWriter tw=new StringWriter(sb);
6 export.Execute(new Action<string>((string x) => { Console.Write(x); }), true, true,tw);
7 }
測試
SchemaUpadte使用
原來的映射檔案Product.hbm.xml。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Wolfy.Shop.Domain" namespace="Wolfy.Shop.Domain.Entities">
3 <class name="Wolfy.Shop.Domain.Entities.Product,Wolfy.Shop.Domain" table="TB_Product">
4 <id name="ProductID" column="ProductID" type="Guid" unsaved-value="null">
5 <generator class="assigned" />
6 </id>
7 <property name="Name" column="Name" type="String"
8 not-null="true" />
9 <property name="Price" column="Price" type="decimal"
10 not-null="true" />
11 <!--多對多關系:product屬于多個orders-->
12 <bag name="Orders" generic="true" table="TB_OrderProduct" >
13 <key column="ProductID" foreign-key="FK_TB_OrderProduct_TB_Product"/>
14 <many-to-many column="OrderID" class="Wolfy.Shop.Domain.Entities.Order,Wolfy.Shop.Domain"
15 foreign-key="FK_TB_OrderProduct_TB_Order"/>
16 </bag>
17 </class>
18 </hibernate-mapping>
修改映射檔案,添加一個庫存量的字段。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Wolfy.Shop.Domain" namespace="Wolfy.Shop.Domain.Entities">
3 <class name="Wolfy.Shop.Domain.Entities.Product,Wolfy.Shop.Domain" table="TB_Product">
4 <id name="ProductID" column="ProductID" type="Guid" unsaved-value="null">
5 <generator class="assigned" />
6 </id>
7 <property name="Name" column="Name" type="String"
8 not-null="true" />
9 <property name="Price" column="Price" type="decimal"
10 not-null="true" />
11 <!--庫存-->
12 <property name="ProductCount" column="ProductCount" type="int"
13 not-null="true" />
14 <!--多對多關系:product屬于多個orders-->
15 <bag name="Orders" generic="true" table="TB_OrderProduct" >
16 <key column="ProductID" foreign-key="FK_TB_OrderProduct_TB_Product"/>
17 <many-to-many column="OrderID" class="Wolfy.Shop.Domain.Entities.Order,Wolfy.Shop.Domain"
18 foreign-key="FK_TB_OrderProduct_TB_Order"/>
19 </bag>
20 </class>
21 </hibernate-mapping>
測試,在資料層添加一個類SchemaUpdateFixture
1 /// <summary>
2 /// 描述:SchemaExport修改資料庫架構操作類
3 /// 建立人:wolfy
4 /// 建立時間:2014-11-16
5 /// </summary>
6 public class SchemaUpdateFixture
7 {
8 private Configuration _cfg;
9 public SchemaUpdateFixture()
10 {
11 _cfg = new Configuration();
12 _cfg.Configure();
13 var export = new SchemaExport(_cfg);
14 export.Execute(true, true, false);
15
16 }
17 public void UpdateTest()
18 {
19 _cfg = new Configuration();
21 _cfg.Configure();
22 var export = new SchemaUpdate(_cfg);
23 export.Execute(true, true);
24 }
25 }
檢視生成的資料表TB_Product
細心的你可能會發現,我們在修改過映射檔案後并沒有修改對應的持久化類。通過SchemaUpdate(_cfg)你就會發現,初始化該工具的時候隻是加載對應的配置檔案,跟持久化類并沒關系,不過為了對應關系,還是在修改過映射檔案後,将添加的或者删除的字段,在持久化類中修改一下,以免忘記,造成打錯。
本篇文章通過執行個體介紹NHibernate中提供的兩個實用工具SchemaExport如何利用持久化類和映射檔案生成資料庫架構。本篇文章就介紹到這裡。
參考文章:http://www.cnblogs.com/lyj/archive/2008/11/11/1331509.html
-
部落格位址:http://www.cnblogs.com/wolf-sun/
部落格版權:如果文中有不妥或者錯誤的地方還望高手的你指出,以免誤人子弟。如果覺得本文對你有所幫助不如【推薦】一下!如果你有更好的建議,不如留言一起讨論,共同進步!
再次感謝您耐心的讀完本篇文章。