摘要
在实际的项目中,经常是将NHibernate的实体关系映射类做成独立的工程(assembly dll),只对外提供Session调用的接口。这个程序集作为数据访问层,可以被上面的多个工程(ASP.Net、Windows Form、Windows Serviice等)调用。
这篇文章介绍如何设计NHibernate数据访问层的工程,以及如何架构数据访问层和上面的应用层的关系。
本文章的所有代码可以到第一个NHibernate程序下载。
步骤:
1)为了后面文章的程序演示方便,删除Customer表,新建主键类型是int类型,主键生成方法是IDENTITY的Customer表。
CREATE TABLE [dbo].[Customer]( [Id] [int] IDENTITY(1,1) NOT NULL, [FirstName] [nvarchar](10) NOT NULL, [LastName] [nvarchar](10) NOT NULL, [Points] [int] NULL, [HasGoldStatus] [bit] NULL, [MemberSince] [date] NULL, [CreditRating] [nchar](20) NULL, [AverageRating] [decimal](18, 4) NULL, [Street] [nvarchar](100) NULL, [City] [nvarchar](100) NULL, [Province] [nvarchar](100) NULL, [Country] [nvarchar](100) NULL, CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
2)添加Class Library:NHibernateDemoAPP.XML.Entities。删除Class1.cs文件。
这里使用XML映射,因此这里用NHibernateDemoAPP.XML.Entities作为工程名。实际项目的工程名称应该没有"XML"。
3)在NHibernateDemoAPP.XML.Entities工程里添加文件夹Domain和hbm。也可以创建名称为Mapping的文件夹,替代这里的hbm文件夹,看个人喜好。
4)将NHibernateDemoApp工程的文件Address.cs、Customer.cs移动到Domain文件夹。将文件Customer.hbm.xml移动到hbm文件夹。在NHibernateDemoApp工程里删除文件Address.cs、Customer.cs和Customer.hbm.xml。
5)修改NHibernateDemoApp工程的文件hibernate.hbm.xml。修改mapping节点的assembly属性。
<?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <property name="connection.connection_string_name">default</property> <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property> <mapping assembly="NHibernateDemoAPP.XML.Entities"/> </session-factory> </hibernate-configuration>
6)修改Customer.cs的namespace。将Id属性改成int。
1 using System; 2 3 namespace NHibernateDemoAPP.XML.Entities.Domain 4 { 5 public class Customer 6 { 7 public virtual int Id { get; set; } 8 public virtual string FirstName { get; set; } 9 public virtual string LastName { get; set; } 10 public virtual double AverageRating { get; set; } 11 public virtual int Points { get; set; } 12 public virtual bool HasGoldStatus { get; set; } 13 public virtual DateTime MemberSince { get; set; } 14 public virtual CustomerCreditRating CreditRating { get; set; } 15 public virtual Address Address { get; set; } 16 } 17 18 public enum CustomerCreditRating 19 { 20 Excellent, VeryVeryGood, VeryGood, Good, Neutral, Poor, Terrible 21 } 22 }
7)修改Customer.hbm.xml文件。修改根节点hibernate-mapping的assembly属性和namespace属性。
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemoAPP.XML.Entities" namespace="NHibernateDemoAPP.XML.Entities.Domain"> <class name="Customer" table="Customer"> <id name="Id"> <generator class="native"/> </id> <property name="FirstName" not-null="true"/> <property name="LastName" not-null ="true"/> <property name="AverageRating"/> <property name="Points"/> <property name="HasGoldStatus"/> <property name="MemberSince"/> <property name="CreditRating" type="CustomerCreditRating"/> <component name="Address"> <property name="Street"/> <property name="City"/> <property name="Province"/> <property name="Country"/> </component> </class> </hibernate-mapping>
8)为工程NHibernateDemoApp添加工程NHibernateDemoAPP.XML.Entities的引用。
9)修改Program.cs文件。
1 using NHibernate; 2 using NHibernate.Cfg; 3 using NHibernateDemoAPP.XML.Entities.Domain; 4 using System; 5 using System.Collections.Generic; 6 7 namespace NHibernateDemoApp 8 { 9 class Program 10 { 11 private static ISessionFactory _sessionFactory; 12 13 private static ISession _session; 14 15 public static ISessionFactory SessionFactory 16 { 17 get 18 { 19 if (_sessionFactory == null) 20 { 21 var cfg = new Configuration(); 22 cfg.Configure(); 23 _sessionFactory = cfg.BuildSessionFactory(); 24 } 25 return _sessionFactory; 26 } 27 } 28 29 public static ISession Session 30 { 31 get 32 { 33 if (_session == null) 34 { 35 _session = SessionFactory.OpenSession(); 36 } 37 return _session; 38 } 39 } 40 41 42 static void Main(string[] args) 43 { 44 HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize(); 45 46 using (var session = SessionFactory.OpenSession()) 47 { 48 var customer = CreateCustomer(); 49 object custoemrId = session.Save(customer); 50 session.Flush(); 51 52 customer = session.Get<Customer>(custoemrId); 53 Console.WriteLine(customer.LastName); 54 } 55 56 Console.WriteLine("Completed"); 57 Console.ReadLine(); 58 } 59 60 private static Customer CreateCustomer() 61 { 62 var customer = new Customer 63 { 64 FirstName = "Daniel", 65 LastName = "Tang", 66 Points = 100, 67 HasGoldStatus = true, 68 MemberSince = new DateTime(2012, 1, 1), 69 CreditRating = CustomerCreditRating.Good, 70 AverageRating = 42.42424242, 71 Address = new Address 72 { 73 Street = "123 Somewhere Avenue", 74 City = "Nowhere", 75 Province = "Alberta", 76 Country = "Canada" 77 } 78 }; 79 80 return customer; 81 } 82 83 private static void UpdateInTransaction(Customer customer) 84 { 85 using (var transaction = Session.BeginTransaction()) 86 { 87 try 88 { 89 Session.Update(customer); 90 transaction.Commit(); 91 } 92 catch (HibernateException e) 93 { 94 transaction.Rollback(); 95 throw e; 96 } 97 } 98 } 99 100 private static IList<Customer> GetAll() 101 { 102 using (var session = SessionFactory.OpenSession()) 103 { 104 IList<Customer> list = session.CreateCriteria<Customer>().List<Customer>(); 105 return list; 106 } 107 } 108 109 private static Customer GetById(Guid id) 110 { 111 using (var session = SessionFactory.OpenSession()) 112 { 113 Customer customer = session.Get<Customer>(id); 114 return customer; 115 } 116 } 117 118 private static Customer LoadById(Guid id) 119 { 120 using (var session = SessionFactory.OpenSession()) 121 { 122 Customer customer = session.Load<Customer>(id); 123 return customer; 124 } 125 } 126 127 private static int Insert(Customer customer) 128 { 129 using (var session = SessionFactory.OpenSession()) 130 { 131 var identifier = session.Save(customer); 132 session.Flush(); 133 return Convert.ToInt32(identifier); 134 } 135 } 136 137 private static void Update(Customer customer) 138 { 139 using (var session = SessionFactory.OpenSession()) 140 { 141 session.SaveOrUpdate(customer); 142 session.Flush(); 143 } 144 } 145 146 private static void Delete(int id) 147 { 148 using (var session = SessionFactory.OpenSession()) 149 { 150 var customer = session.Get<Customer>(id); 151 session.Delete(customer); 152 session.Flush(); 153 } 154 } 155 } 156 }
9)执行程序,将一条Customer对象插入到数据库记录中。
下一篇文章介绍如何在应用层(ASP.Net MVC, ASP.Net Web, Windows Form, Windows Service)中管理SessionFactory对象和Session对象。