剑花 烟雨

   江南  好 风景旧曾谙 日出江花红胜火 春来江水绿如蓝 能不忆东北

理想中的建筑师应该是一个诗人、数学家、精通历史、精通心理学、熟悉音乐、了解医学、还要具备天文学和计算的基本知识。
                                                                                                                         ------------------公元前25年,罗马建筑学家Vitruvius
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
由于文章的主体内容来自于飞鹰,只是我在Vs 2005下将其实现了。所以说转的吧,不过前面的是转的,后面的都是俺自己的体会了。

使用NHibernate开发主要有下面的四个步骤:

       创建实体层的类(Cool Coder工具生成)

/*
  1,在这步就用CodeSmith来生成吧,觉得Cool Code生成的数据类型都是原来长度的一半,另外主要的原因是我用cool code生成的代码没有成功,当然大部分是我的原因。随着对其了解的深入,一些问题也得到了解决。但是,到了解决的时候我就用的是CodeSmith工具了。
***************************************************
2,用这些自动代码生成工具的时候,生成的代码还是要手工去改的,不是生成了就完事大吉了。还是需要我们去了解NHibernate的映射原理,知道哪部分是做什么的,这样改的时候才能够得心应手。主要的参考文献就是NHibernate的帮助和NHibernate的官方网站。查文档的时候第一个要从这里查起。
*************************************
3,CodeSmith在NHibernate开发中的用法参见http://www.cnblogs.com/abluedog/archive/2006/04/15/375862.aspx。在这里已经介绍的很详细了,所以我就不多说了。在做这个工作之前是要读好的。
****************************************
4,在用CodeSmith生成代码的时候,你设计的数据库表一定要有一个自动增长的列,在SQL Server2000或其它的大型数据库中是支持这项功能的。这个是值得引起注意的,不然在更新数据库时候就会有问题了,如果是自己定义的关键字,那就要进行相应的设置,可惜我还没有去探索,时间不允许了。要是有谁知道怎么进行设置,最好在下面回复一下。
***********************************
5,CodeSmith生成的实体类,的属性是要在前面加入virtual关键字的,不然编译器会报错。例子如下(C#代码):
*/

public virtual string Lydwh
        
{
            
get return _lydwh; }
            
set
            
{
                
if ( value != null && value.Length > 10)
                    
throw new ArgumentOutOfRangeException("Invalid value for Lydwh", value, value.ToString());
                _lydwh 
= value;
            }

        }



       公用的数据层代码(使用写好的类)

       生成业务层的代码框架(使用QuickCode插件生成)

//这步可以不用这个工具生成,手写也可以的
//当然也可以用它和一些代码生成工具如CodeSmith生成
//建议还是自己写的好些。

       测试代码

我们下面来一步一步看其实现的过程。

1)             创建实体层的类(工具生成)

       在菜单中选择New建立数据库连接。
 

       选择要生成代码的表。

       设置生成代码的目录,单击生成。
 

       查看生成结果,如下图:
 

生成VB.NET代码如下:(相应的C#代码由CodeSmith生成)

Imports System

              public class  Customers

                            Public Sub New()//vb的空构造函数

                            End Sub 'New

                            private  _Region As System.String

                            Public Property Region() As System.String

                                          Get

                                                        return _Region

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _Region = Value

                                          End Set

                            End Property

 

                            private  _PostalCode As System.String

                            Public Property PostalCode() As System.String

                                          Get

                                                        return _PostalCode

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _PostalCode = Value

                                          End Set

                            End Property

 

                            private  _Fax As System.String

                            Public Property Fax() As System.String

                                          Get

                                                        return _Fax

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _Fax = Value

                                          End Set

                            End Property

 

                            private  _ContactName As System.String

                            Public Property ContactName() As System.String

                                          Get

                                                        return _ContactName

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _ContactName = Value

                                          End Set

                            End Property

 

                            private  _City As System.String

                            Public Property City() As System.String

                                          Get

                                                        return _City

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _City = Value

                                          End Set

                            End Property

 

                            private  _CustomerID As System.String

                            Public Property CustomerID() As System.String

                                          Get

                                                        return _CustomerID

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _CustomerID = Value

                                          End Set

                            End Property

 

                            private  _Address As System.String

                            Public Property Address() As System.String

                                          Get

                                                        return _Address

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _Address = Value

                                          End Set

                            End Property

 

                            private  _ContactTitle As System.String

                            Public Property ContactTitle() As System.String

                                          Get

                                                        return _ContactTitle

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _ContactTitle = Value

                                          End Set

                            End Property

 

                            private  _Phone As System.String

                            Public Property Phone() As System.String

                                          Get

                                                        return _Phone

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _Phone = Value

                                          End Set

                            End Property

 

                            private  _CompanyName As System.String

                            Public Property CompanyName() As System.String

                                          Get

                                                        return _CompanyName

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _CompanyName = Value

                                          End Set

                            End Property

 

                            private  _Country As System.String

                            Public Property Country() As System.String

                                          Get

                                                        return _Country

                                          End Get

                                          Set(ByVal Value As System.String)

                                                        _Country = Value

                                          End Set

                            End Property

End Class


生成的映射的
XML代码如下:

xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">

<class name="ORMDemo.Customers, ORMDemo" table="Customers">//注意这里,在代码中会用到。前面的是持久化类的全限定名,后面的是Assembly的名字。

<id name="CustomerID" column="CustomerID" type="String">

              <generator class="assigned" />

id>

<property name="CompanyName" type="String(40)" column="CompanyName" />

<property name="ContactName" type="String(30)" column="ContactName" />

<property name="ContactTitle" type="String(30)" column="ContactTitle" />

<property name="Address" type="String(60)" column="Address" />

<property name="City" type="String(15)" column="City" />

<property name="Region" type="String(15)" column="Region" />

<property name="PostalCode" type="String(10)" column="PostalCode" />

<property name="Country" type="String(15)" column="Country" />

<property name="Phone" type="String(24)" column="Phone" />

<property name="Fax" type="String(24)" column="Fax" />

class>

hibernate-mapping>

       创建一个空的项目,把代码拷贝进去。

       参照Nhibenate DLL

       你现在就可以使用他们来执行数据库的操作了。

 

2)             公用的数据层代码(使用写好的类)

我们这里使用一个写好的数据库层的访问数据库方法,这样,数据层将不需要再增加任何代码。数据层通用访问方法如下:

//VB 代码
Imports
System

Imports System.Reflection

Imports System.Data

Imports System.Data.SqlClient

 

Imports NHibernate

Imports NHibernate.Cfg

Imports NHibernate.Dialect

Imports NHibernate.Tool.hbm2ddl

 

 

Public Class EntityControl

    Private Shared entity As EntityControl

 

    Protected Shared myCfg As NHibernate.Cfg.Configuration

    Protected Shared dialect As NHibernate.dialect.Dialect

    Protected Shared sessions As ISessionFactory

 

    Public Shared Function CreateControl() As EntityControl

        If entity Is Nothing Then

            BuildSessionFactory()

            If entity Is Nothing Then

                entity = New EntityControl

            End If

        End If

        Return entity

    End Function 'CreateControl

 

    Private Shared Sub BuildSessionFactory()

        ExportSchema(New String() {"Customers.hbm.xml"}, False)

    End Sub 'BuildSessionFactory

 

    Public Sub AddEntity(ByVal entity As Object)

 

        Dim s As ISession = sessions.OpenSession()

        Dim t As ITransaction = s.BeginTransaction()

        Try

            s.Save(entity)

            t.Commit()

        Catch e As Exception

            t.Rollback()

            Throw e

        Finally

            s.Close()

        End Try

    End Sub 'AddEntity

 

 

    Public Sub UpdateEntity(ByVal entity As Object, ByVal key As Object)

        Dim s As ISession = sessions.OpenSession()

        Dim t As ITransaction = s.BeginTransaction()

        Try

            s.Update(entity, key)

            t.Commit()

        Catch e As Exception

            t.Rollback()

            Throw e

        Finally

            s.Close()

        End Try

    End Sub 'UpdateEntity

 

    Public Sub DeleteEntity(ByVal entity As Object)

        Dim s As ISession = sessions.OpenSession()

        Dim t As ITransaction = s.BeginTransaction()

        Try

            s.Delete(entity)

            t.Commit()

        Catch e As Exception

            t.Rollback()

            Throw e

        Finally

            s.Close()

        End Try

    End Sub 'DeleteEntity

 

 

    Public Function GetEntities(ByVal query As String) As IList

        Dim lst As IList

        Dim s As ISession = sessions.OpenSession()

        Dim t As ITransaction = s.BeginTransaction()

 

        lst = s.Find(query)

        t.Commit()

        s.Close()

        Return lst

    End Function 'GetEntities

 

    Public Function GetEntity(ByVal theType As System.Type, ByVal id As Object) As Object

 

        Dim obj As Object

        Dim s As ISession = sessions.OpenSession()

        Dim t As ITransaction = s.BeginTransaction()

        obj = s.Load(theType, id)

        t.Commit()

        s.Close()

 

        Return obj

    End Function 'GetEntity

 

 

    Private Overloads Shared Sub ExportSchema(ByVal files() As String) '

 

        ExportSchema(files, True)

    End Sub 'ExportSchema

 

    Private Overloads Shared Sub ExportSchema(ByVal files() As String, ByVal exportSchema As Boolean)

        myCfg = New NHibernate.Cfg.Configuration

        Dim i As Integer

        For i = 0 To files.Length - 1

            myCfg.AddResource("ORMDemo." + files(i), [Assembly].Load("ORMDemo"))

        Next i

        If exportSchema Then

            Dim se As New SchemaExport(myCfg)

            se.Create(True, True)

        End If

        sessions = myCfg.BuildSessionFactory()

        dialect = NHibernate.Dialect.Dialect.GetDialect()

    End Sub 'ExportSchema

 

    '/

    '/ Drops the schema that was built with the TestCase's Configuration.

    '/

    Private Shared Sub DropSchema()

        Dim se As New SchemaExport(myCfg)

        se.Drop(True, True)

    End Sub 'DropSchema

 

    Private Overloads Shared Sub ExecuteStatement(ByVal sql As String)

        ExecuteStatement(sql, True)

    End Sub 'ExecuteStatement

 

    Private Overloads Shared Sub ExecuteStatement(ByVal sql As String, ByVal [error] As Boolean)

        Dim conn As IDbConnection = Nothing

        Dim tran As IDbTransaction = Nothing

        Try

            If myCfg Is Nothing Then

                myCfg = New NHibernate.Cfg.Configuration

            End If

            Dim prov As NHibernate.Connection.IConnectionProvider = NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(myCfg.Properties)

            conn = prov.GetConnection()

            tran = conn.BeginTransaction()

            Dim comm As IDbCommand = conn.CreateCommand()

            comm.CommandText = sql

            comm.Transaction = tran

            comm.CommandType = CommandType.Text

            comm.ExecuteNonQuery()

            tran.Commit()

        Catch exc As Exception

            If Not (tran Is Nothing) Then

                tran.Rollback()

            End If

            If [error] Then

                Throw exc

            End If

        Finally

            If Not (conn Is Nothing) Then

                conn.Close()

            End If

        End Try

    End Sub 'ExecuteStatement

 

End Class 'EntityControl


 

相应的C#代码如下:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Tool.hbm2ddl;
using Iesi.Collections ;
using System.Reflection;
using System.Collections;


/// <summary>
/// Summary description for EntityControl
/// </summary>

public class EntityControl
{
    
private static EntityControl entity ;
    
protected static NHibernate.Cfg.Configuration myCfg;
    
protected static NHibernate.Dialect.Dialect dialect;
    
protected static NHibernate.ISessionFactory sessions;

    
public EntityControl()
    
{
        
//
        
// TODO: Add constructor logic here
        
//
     
    }


    
public  static EntityControl CreateControl()
    
{
        
if (entity == null  )
        
{
            BuildSessionFactory();
            
if (entity == null )
            
{
                entity 
= new EntityControl();
            }

        }

        
return entity;
    }

    
private static void BuildSessionFactory()
    
{
        ExportSchema(
new string[] {"HostMachine.hbm.xml"}false);
    }

    
private  static void ExportSchema(string[] files)
    
{
        ExportSchema(files,
true);
    }

    
private static void ExportSchema(string[] files, bool exportSchema)
    
{
        myCfg 
= new NHibernate.Cfg.Configuration();
        
int i;
        
for (i = 0; i <= files.Length - 1; i++)
        
{
            
  myCfg.AddXmlFile(files[i]);
        }

        
if (exportSchema)
        
{
            SchemaExport se 
= new SchemaExport(myCfg);
            se.Create(
truetrue);
        }

        sessions 
= myCfg.BuildSessionFactory();
        
dialect = NHibernate.Dialect.Dialect.GetDialect();
    }

    
public void AddEntity(Object entity)
    
{
        
        ISession s 
= sessions.OpenSession();
        ITransaction t 
= s.BeginTransaction();

        
try
        
{
            s.Save(entity);
            t.Commit();
        }

        
catch (Exception e)
        
{
            t.Rollback();
            
throw e;
        }

        
finally
        
{
            s.Close();
        }

    }

    
public void UpdateEntity(Object entity, Object key)
    
{
        ISession s 
= sessions.OpenSession();
        ITransaction t 
= s.BeginTransaction();

        
try
        
{
            s.Update(entity, key);
            t.Commit();
        }

        
catch(Exception e)
        
{
            t.Rollback();
            
throw e;
        }

        
finally
        
{
            s.Close();
        }

    }

    
public void DeleteEntity(Object entity)
    
{
        ISession s 
= sessions.OpenSession();
        ITransaction t 
= s.BeginTransaction();

        
try
        
{
            s.Delete(entity);
            t.Commit();
        }

        
catch (Exception e)
        
{
            t.Rollback();
            
throw e;
        }

        
finally
        
{
            s.Close();
        }

    }

    
   public IList GetEntities(string query)
    
{
        IList lst;
        ISession s 
= sessions.OpenSession();
        ITransaction t 
= s.BeginTransaction();

        lst 
= s.CreateQuery(query).List ();
        t.Commit();
        s.Close();
        
return lst;
    }

    
public Object GetEntity(System.Type theType, Object id)
    
{
        Object obj;
        ISession s 
= sessions.OpenSession();
        ITransaction t 
= s.BeginTransaction();

        obj 
= s.Load(theType, id);

        t.Commit();
        s.Close();

        
return obj;
    }

    
// Drops the schema that was built with the TestCase's Configuration.
    private static void DropSchema()
    
{
        SchemaExport se 
= new SchemaExport(myCfg);
        se.Drop(
true,true);
    }

    
private static void ExecuteStatement(string sql)
    
{
        ExecuteStatement(sql, 
true);
    }

    
private static void ExecuteStatement(string sql,bool error)
    
{
        IDbConnection conn 
= null;
        IDbTransaction tran 
= null;

        
try
        
{
            
//has errors
            if (Object.Equals(myCfg,null ))
            
{
                myCfg 
= new NHibernate.Cfg.Configuration();
            }

            NHibernate.Connection.IConnectionProvider prov 
= NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(myCfg.Properties);
            conn 
= prov.GetConnection();
            tran 
= conn.BeginTransaction();
            IDbCommand comm 
= conn.CreateCommand();
            comm.CommandText 
= sql;
            comm.Transaction 
= tran;
            comm.CommandType 
= CommandType.Text;
            comm.ExecuteNonQuery();
            tran.Commit();
        }

        
catch(Exception exc)
        
{
            
if (!Object.Equals(tran, null))
            
{
                tran.Rollback();
            }

            
if (error)
            
{
                
throw exc;
            }

        }

        
finally
        
{
            
if (!(Object.Equals (conn,null )))
            
{
                conn.Close ();
            }


        }

    }

}

 

3)             生成业务层的代码框架(使用QuickCode插件生成)

我们使用QuickCode可以自动生成,业务层的增删改框架,我们只需要增加业务处理的功能即可。

自动生成的业务层代码如下:

'------------------------------------------------------------------------

' Copyright (C) 2000-2004 GrapeCity Corporation

' All rights reserved.

'

' Description:

'   Customer class

'

' Created By:       Tim Wang

' Date Created:     21-09-2004

'

' Modified History:

' Date          By                  Description

' ----------    ----------------    -------------------------------------

'------------------------------------------------------------------------

 

Public Class CustomerBR

    Dim control As EntityControl

    Sub New()//VB的构造函数

        control = EntityControl.CreateControl()

    End Sub

    '-------------------------------------------------------------------------

    ' Name: Add

    '

    ' Description:  The Add method is used to Add Customer in BusinessRule layer.

    '

    ' Created By:       Tim Wang

    ' Date Created:     21-09-2004

    '--------------------------------------------------------------------------

    Public Sub Add(ByVal Customer As Customers)

        Check(Customer)

        control.AddEntity(Customer)

    End Sub

    '-------------------------------------------------------------------------

    ' Name: Update

    '

    ' Description:  The Update method is used to Update Customer in BusinessRule layer.

    '

    ' Created By:       Tim Wang

    ' Date Created:     21-09-2004

    '--------------------------------------------------------------------------

    Public Sub Update(ByVal Customer As Customers)

        control.UpdateEntity(Customer, Customer.CustomerID)

    End Sub

    '-------------------------------------------------------------------------

    ' Name: Delete

    '

    ' Description:  The Delete method is used to Delete Customer in BusinessRule layer.

    '

    ' Created By:       Tim Wang

    ' Date Created:     21-09-2004

    '--------------------------------------------------------------------------

    Public Sub Delete(ByVal Customer As Customers)

        control.DeleteEntity(Customer)

    End Sub

 

    '-------------------------------------------------------------------------

    ' Name: GetCustomers

    '

    ' Description:  The GetCustomers method is used to Get Customers in BusinessRule layer.

    '

    ' Created By:       Tim Wang

    ' Date Created:     21-09-2004

    '--------------------------------------------------------------------------

    Public Function GetCustomers(ByVal query As String) As IList

        Return control.GetEntities(query)

    End Function

 

    '-------------------------------------------------------------------------

    ' Name: GetSingleCustomer

    '

    ' Description:  The GetSingleCustomer method is used to Get a single Customer in BusinessRule layer.

    '

    ' Created By:       Tim Wang

    ' Date Created:     21-09-2004

    '--------------------------------------------------------------------------

    Public Function GetSingleCustomer(ByVal CustomerID As String) As Customers

        Return CType(control.GetEntity(GetType(Customers), CustomerID), Customers)

    End Function

 

    Private Sub Check(ByVal Customer As Customers)

    End Sub

End Class

 

 

我们留一个Check方法来做业务数据的检查。(把这个函数直接写入上面的空函数中即可

如下:

    Private Sub Check(ByVal Customer As Customers)

        If Customer.CustomerID = "911" Then

            Throw New ApplicationException("911 is not suitable to be used to CustomerID.")

        End If

    End Sub

 

 

4)             测试代码

 

我们来编写调用的测试代码,如下:

Imports NUnit.Framework

 

_

Public Class TestCustomer

 

    Dim Cust As CustomerBR

    Dim customer As Customers

    Dim customerID As String

    _

    Public Sub init()

        Cust = New CustomerBR

        customerID = "003"

 

    End Sub

    _

    Public Sub Add()

        customer = New Customers

        Dim count As Integer

        count = Cust.GetCustomers("from c in class Customers").Count

        With customer

            .CustomerID = customerID

            .CompanyName = "GPCT"

            .Country = "China"

        End With

        Cust.Add(customer)

        Assert.AreEqual(count + 1, Cust.GetCustomers("from c in class Customers").Count)

    End Sub

    _

    Public Sub Modify()

        customer = Cust.GetSingleCustomer(customerID)

        Assert.AreEqual("China", customer.Country)

        customer.Country = "Japan"

        Cust.Update(customer)

 

        customer = Cust.GetSingleCustomer(customerID)

 

        Assert.IsFalse(customer.Country = "China")

 

        Assert.AreEqual("Japan", customer.Country)

    End Sub

 

    _

    Public Sub Delete()

        customer = New Customers

        customer.CustomerID = customerID

 

        Assert.AreEqual(1, Cust.GetCustomers("from c in class Customers where c.CustomerID = '" & customerID & "'").Count)

        Cust.Delete(customer)

 

        Assert.AreEqual(0, Cust.GetCustomers("from c in class Customers where c.CustomerID = '" & customerID & "'").Count)

 

    End Sub

 

    GetType(ApplicationException))> _

    Public Sub TestBusinessRule()

        customer = New Customers

      

        With customer

            .CustomerID = "9111"

            .CompanyName = "GPCT"

            .Country = "China"

        End With

        Cust.Add(customer)

    End Sub

 

End Class

 

5)             数据库字段修改演示

我们把Customers表中的Country字段修改为country1,这时候测试代码失败。修改xml文件,再运行测试代码,程序通过。

 

结论:我们修改字段名称时,只需要修改XML文件即可,程序不做任何改动。

 

6)             数据库字段增加演示

我们在数据库中增加一字段aaa,重新生成实体类和XML文件,即可使用新的实体类,程序不需要做任何改变。

 

结论:修改字段时只在需要增加新字段的内容的地方作修改,不需要增加任何其他代码。

 

7)             数据库字段删除演示

我们删除一列,重新生成实体类和XML文件,程序会在需要修改的地方提示,只要删除此除代码即可,其它程序不做任何改动。

 

8)             把结果转变成DataSet

如果想把返回的IList转变成DataSet,我们只要调一个通用的方法即可,而如果想从DataSet转变成实体类组成的IList,将会非常复杂。

 

转换成DataSet的通用的方法如下:

    Private Function ConvertToDS(ByVal lst As IList, ByVal typ As System.Type) As DataSet

        Dim obj As Object

        Dim ds As New DataSet

 

        Dim tbl As DataTable = ds.Tables.Add(typ.Name)

 

        ' Get the public properties.

        Dim myPropertyInfo As System.Reflection.PropertyInfo() = typ.GetProperties((System.Reflection.BindingFlags.Public Or System.Reflection.BindingFlags.Instance))

 

 

        Dim pi As System.Reflection.PropertyInfo

        For Each pi In myPropertyInfo

            tbl.Columns.Add(pi.Name, System.Type.GetType(pi.PropertyType.ToString()))

        Next

 

 

        For Each obj In lst

            Dim dr As DataRow = tbl.NewRow

 

            For Each pi In myPropertyInfo

                dr(pi.Name) = pi.GetValue(obj, Nothing)

            Next

            tbl.Rows.Add(dr)

 

        Next

        Return ds

    End Function

使用上面的方法来生成DataSet的方法如下:

Dim Cust As New CustomerBR

Dim customerLst As IList

customerLst = Cust.GetCustomers("from Customers")

 

Dim myType As System.Type = GetType(Customers)

DataGrid1.DataSource = ConvertToDS(customerLst, myType).Tables(0

count hit
欢迎您到紫阁阳光坐客