[Nhibernate]SchemaExport工具的使用(一)——通过映射文件修改数据表

目录

写在前面

文档与系列文章

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]存储过程的使用(三)

SchemaExport工具

NHibernate的hbm2dll提供SchemaExport工具:给定一个连接字符串和映射文件,不需输入其他东西就可以按照持久化类和映射文件自动生成数据库架构,现在SchemaExport工具还不是很强大,但是一般应用足够了,它还是一个相当原始的API还在不断改进。

SchemaExport工具就是把DDL脚本输出到标准输出,同时/或者执行DDL语句。SchemaExport工具提供了三个方法,分别是Drop()、Create()、Execute(),前两个方法实质是调用Execute()方法。通常使用Execute()方法来生成数据库架构的。

SchemaUpdate工具

在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         }

生成的sql语句

通过最后一条你也会发现,连视图也生成了。

测试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         }

生成的sql语句

通过比较你会发现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

posted @ 2014-11-16 14:32  wolfy  阅读(2276)  评论(0编辑  收藏  举报