NHibernate初学者指南(14):配置的三种方式

XML配置

配置NHibernate最初是通过XML。我们有两种方式可以定义配置,一种是Windows应用程序的应用程序配置文件,另一种是基于web的应用程序的Web.config文件。我们也可以在单独的XML文件中定义配置。

下面我们通过一个例子,实现一个简单的应用程序,使用NHibernate持久化数据并从关系数据库中读取数据。我们使用的数据库是SQLite。

1. 打开Visual Studio,创建一个控制台应用程序:XmlConfigurationSample。

2. 在Solution Explorer中,右击XmlConfigurationSample项目,选择属性,在Application选项卡中,将Target framework设置为.NET Framework3.5。

3. 在Build选项卡中,确保Platform Target设置为了Any CPU。

4. 添加对NHibernate.dll, NHibernate.ByteCode.Castle.dll和System.Data.SQLite.dll程序集的引用。

5. 在解决方案中添加一个解决方案文件夹:Schema。

6. 在Schema解决方案文件夹中添加两个文件:nhibernate-configuration.xsd和nhibernate-mapping.xsd。

7. 在项目中添加一个类文件:Account.cs,添加如下代码:

public class Account
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Balance { get; set; }
    public string CurrencyCode { get; set; }
    public bool IsActive { get; set; }
}

8. 在项目中添加一个XML文件:Account.hbm.xls用于定义Account实体的映射,代码如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="XmlConfigurationSample"
namespace="XmlConfigurationSample" >
  <class name="Account" lazy="false">
    <id name="Id">
      <generator class="hilo"/>
    </id>
    <property name="Name"/>
    <property name="Balance"/>
    <property name="CurrencyCode"/>
    <property name="IsActive"/>
  </class>
</hibernate-mapping>

9. 设置Account.hbm.xml的BuilAction属性为:Embedded Resource。

10. 打开项目中的app.config文件(如果没有添加一个),定义一个section:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  </configSections>
</configuration>

11. 在configSections后面,添加如下代码:

  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">
        NHibernate.Connection.DriverConnectionProvider
      </property>
      <property name="connection.driver_class">
        NHibernate.Driver.SQLite20Driver
      </property>
      <property name="dialect">
        NHibernate.Dialect.SQLiteDialect
      </property>
      <property name="proxyfactory.factory_class">
        NHibernate.ByteCode.Castle.ProxyFactoryFactory,
        NHibernate.ByteCode.Castle
      </property>
      <property name="connection.connection_string_name">
        Sample
      </property>
      <property name="show_sql">
        true
      </property>
    </session-factory>
  </hibernate-configuration>

12. 在上面代码的后面再定义一个数据库连接字符串,代码如下:

  <connectionStrings>
  <add name="Sample" connectionString="data source=xmlconfig.dbf;version=3;new=true;"/>
  </connectionStrings>

13. 在Program类中添加如下代码,前面都提到过了,这里把所有代码一下子贴出来了。

class Program
{
    static void Main(string[] args)
    {
        var configuration = new Configuration();
        configuration.AddAssembly(typeof(Account).Assembly);
        BuildSchema(configuration);
        var factory = configuration.BuildSessionFactory();
        using (var session = factory.OpenSession())
        {
            var account = new Account
            {
                Name = "USB-10234-R1",
                Balance = 1545.55m,
                CurrencyCode = "CHF",
                IsActive = true
            };
            session.Save(account);
            session.Flush();
            session.Clear();
            var fromDb = session.Get<Account>(account.Id);
            System.Console.Write("\r\n\nHit enter to exit:");
            System.Console.ReadLine();
        }
    }

    private static void BuildSchema(Configuration configuration)
    {
        new SchemaExport(configuration).Execute(true, true, false);
    }
}

14. 运行程序,结果如下图所示:

QQ截图20111124190525

代码中配置

如果不在XML中配置,也可以在代码中定义所有的配置。

下面还是通过一个例子,实现一个简单的应用程序,所有的配置都在代码中定义。

1. 打开SSMS,创建一个数据库:CodeConfigurationSample。

2. 打开Visual Studio创建一个控制台应用程序:CodeConfigurationSample。

3. 添加对Nhibernate.dll和NHibernate.ByteCode.Castle.dll程序集的引用。

4. 在解决方案中添加一个解决方案文件夹:Schema。

5. 在Schema解决方案文件夹中添加两个文件:nhibernate-configuration.xsd和nhibernate-mapping.xsd。

6. 在项目中添加一个类文件Product.cs,添加如下代码定义Product实体:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal UnitPrice { get; set; }
    public int ReorderLevel { get; set; }
    public int UnitsOnStock { get; set; }
    public bool Discontinued { get; set; }
}

7. 添加一个XML文件:Product.hbm.xml,同时将它的BuildAction设置为Embedded Resource。

8. 在Product.hbm.xml中添加如下代码定义Product实体的映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="CodeConfigurationSample" namespace="CodeConfigurationSample" >
  <class name="Product" lazy="false">
    <id name="Id">
      <generator class="hilo"/>
    </id>
    <property name="Name"/>
    <property name="UnitPrice"/>
    <property name="ReorderLevel"/>
    <property name="UnitsOnStock"/>
    <property name="Discontinued"/>
  </class>
</hibernate-mapping>

9. 在Program类中添加一个静态方法GetConfiguration,代码如下:

private static Configuration GetConfiguration()
{
}

10. 首先,我们在GetConfiguration方法中,创建一个Configuration类型的实例,代码如下:

var cfg = new Configuration();

11. 下面通过Add方法,往Properties集合中添加键值对,定义NHibernate使用的ConnectionProvider,ConnectionDriver,Dialect,ProxyFactoryFactoryClass等等,代码如下:

            cfg.Properties.Add(NHibernate.Cfg.Environment.ConnectionProvider, typeof(DriverConnectionProvider).FullName);
            cfg.Properties.Add(NHibernate.Cfg.Environment.ConnectionDriver, typeof(SqlClientDriver).FullName);
            cfg.Properties.Add(NHibernate.Cfg.Environment.Dialect, typeof(MsSql2008Dialect).FullName);
            cfg.Properties.Add(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName);
            cfg.Properties.Add(NHibernate.Cfg.Environment.ConnectionString,
@"server=.;database=CodeConfigurationSample;integrated security=SSPI;");
            cfg.Properties.Add(NHibernate.Cfg.Environment.ShowSql, "true");

12. 现在需要声明想使用的映射,我们既可以单独的添加实体类型,也可以添加包含所有XML配置文件的程序集,代码分别如下:

//cfg.AddClass(typeof(Product));
cfg.AddAssembly(typeof(Product).Assembly);

13. 最后返回cfg。

return cfg;

14. 在Program里定义另一个静态方法BuildSchema,代码如下:

private static void BuildSchema(Configuration configuration)
{
    new SchemaExport(configuration).Execute(true, true, false);
}

15. 下面在Main方法中添加如下代码:

static void Main(string[] args)
{
    var configuration = GetConfiguration();
    BuildSchema(configuration);
    var factory = configuration.BuildSessionFactory();
    using (var session = factory.OpenSession())
    {
        var product = new Product
        {
            Name = "Apple",
            UnitPrice = 1.55m,
            ReorderLevel = 10,
            UnitsOnStock = 5
        };
        session.Save(product);
        session.Flush();
        session.Clear();
        var fromDb = session.Get<Product>(product.Id);
        System.Console.Write("\r\n\nHit enter to exit:");
        System.Console.ReadLine();
    }

16. 运行程序,结果如下图所示:

QQ截图20111124210924

17. 一般情况下,我们并不想将连接字符串定义在代码中,而是放在配置文件中。我们可以在项目中添加一个App.config文件,添加如下代码:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="Sample"
    connectionString="server=.;database=CodeConfigurationSample;integrated security=SSPI;"/>
  </connectionStrings>
</configuration>

18. 在GetConfiguration方法中,修改连接字符串如下:

cfg.Properties.Add(NHibernate.Cfg.Environment.ConnectionStringName, "Sample");

19. 再次运行程序即可。

Fluent配置

使用Loquacious配置NHibernate

NHibernate为配置包含了一个新的fluent API。这个API定义在Loquacious命名空间中,它包含了配置的所有方面。

跟之前一样,我们不讨论太多的理论,而是直接深入例子。在这个例子中,使用前面提到的一些概念,如值对象的使用和NHibernate Profiler工具。

1. 打开Visual Studio,创建一个控制台应用程序:LoquaciousConfigurationSample。

2. 在这个例子中我们还是使用SQLite作为数据库,因此需要相应的调整一下项目设置。在Solution Explorer,右击选择属性,在Application选项卡中选择.NET Framework 3.5作为Target framework,在Build选项卡中确保Platform target设置为Any CPU。

4. 在解决方案中添加一个解决方案文件夹:Schema,在其中添加两个文件:nhibernate-configuration.xsd和nhibernate-mapping.xsd。

5. 在项目中添加对以下程序集的引用:

  • NHibernate.dll
  • NHibernate.ByteCode.Castle.dll
  • HibernatingRhinos.Profiler.Appender.dll
  • System.Data.SQLite.dll

6. 如果项目中没有app.config文件,则添加一个并添加如下代码:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="Sample"
    connectionString="data source=loquaciousConfig.dbf;version=3;new=true;"/>
  </connectionStrings>
</configuration>

7. 在项目中添加一个类文件:Person.cs,添加如下代码定义Person实体:

public class Person
{
    public Guid Id { get; set; }
    public Name Name { get; set; }
    public string SSN { get; set; }
    public DateTime Birthdate { get; set; }
}

8. 添加另一个类文件:Name.cs,添加如下代码定义Name值对象:

public class Name
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string MiddleName { get; set; }

    public bool Equals(Name other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.FirstName, FirstName) &&
        Equals(other.LastName, LastName) &&
        Equals(other.MiddleName, MiddleName);
    }
    public override bool Equals(object obj)
    {
        if (obj.GetType() != typeof(Name)) return false;
        return Equals((Name)obj);
    }
    public override int GetHashCode()
    {
        unchecked
        {
            int result = (FirstName != null ?
            FirstName.GetHashCode() : 0);
            result = (result * 397) ^ (LastName != null ?
            LastName.GetHashCode() : 0);
            result = (result * 397) ^ (MiddleName != null ?
            MiddleName.GetHashCode() : 0);
            return result;
        }
    }
}

9. 在项目中添加一个XML文件:Person.hbm.xml,并将它的Build Action属性设置为Embedded Resource。

10. 在Person.hbm.xml中添加如下代码定义Person实体的映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="LoquaciousConfigurationSample" namespace="LoquaciousConfigurationSample" >
  <class name="Person" lazy="false">
    <id name="Id">
      <generator class="guid.comb"/>
    </id>
    <component name="Name">
      <property name="FirstName"/>
      <property name="LastName"/>
      <property name="MiddleName"/>
    </component>
    <property name="SSN"/>
    <property name="Birthdate"/>
  </class>
</hibernate-mapping>

11. 我们Main方法中添加以下代码使用NHibernate Profiler数据库通过NHibernate与应用程序的通信:

HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();

12. 最后使用位于NHibernate.Cfg.Loquacious命名空间中的fluent API配置NHibernate。首先在Program类中添加一个静态方法:GetConfiguratioin,它包含以下配置的代码:

private static Configuration GetConfiguration()
{
    var cfg = new Configuration();
    cfg.Proxy(p =>
    {
        p.ProxyFactoryFactory<ProxyFactoryFactory>();
    });
    cfg.DataBaseIntegration(db =>
    {
        db.ConnectionProvider<DriverConnectionProvider>();
        db.Driver<SQLite20Driver>();
        db.Dialect<SQLiteDialect>();
        db.ConnectionStringName = "Sample";
        db.LogSqlInConsole = true;
    });
    cfg.AddAssembly(typeof(Person).Assembly);
    return cfg;
}

13. 然后在Program类中再添加一个静态方法:BuildSchema,用来重新创建数据库架构

private static void BuildSchema(Configuration configuration)
{
    new SchemaExport(configuration).Execute(true, true, false);
}

14. 最后在Main方法中添加如下代码,跟前面两个例子是一样的:

var configuration = GetConfiguration();
           BuildSchema(configuration);
           var factory = configuration.BuildSessionFactory();
           using (var session = factory.OpenSession())
           {
               var person = new Person
               {
                   Name = new Name
                   {
                       LastName = "Doe",
                       FirstName = "John",
                       MiddleName = "A."
                   },
                   Birthdate = new DateTime(1977, 1, 6),
                   SSN = "111-22-3333"
               };
               session.Save(person);
               session.Flush();
               session.Clear();
               var fromDb = session.Get<Person>(person.Id);
               Console.Write("\r\n\nHit enter to exit:");
               Console.ReadLine();

15. 启动NHibernate Profiler。

16. 运行程序,监视NHibernate Profiler的输出,如下图所示:

QQ截图20111125102432

17. 可以看到使用了两个session,第一个用来重新创建数据库架构,第二个用来保存和加载person对象。让我们仔细的看一下创建表的脚本,如下图:

QQ截图20111125103238

18. 让我们看一下INSERT语句,如下图所示:

QQ截图20111125103524

19. 最后看一下SELECT语句,如下图所示:

QQ截图20111125103622

总结

本篇通过三个例子分别演示了NHibernate配置的三种方式,即XML配置,代码中配置,和使用NHibernate的fluent API配置。文中都给出了完整的代码,还有所涉及到的知识跟前面紧密相连。

posted @ 2011-11-25 10:44  BobTian  阅读(9342)  评论(6编辑  收藏  举报