NHibernate 3.2 Mapping By Code 操纵实例

来源:互联网 发布:鸿雁传书软件下载 编辑:程序博客网 时间:2024/06/05 05:29

繼Linq to SQL、Entity Framework之後,最近又碰了一套ORM就是"NHibernate"

在初步的認識他之後,覺得這套的擴充性與功能方面都十分強大。

當然目前對他的掌握度還沒有很高,因此可能寫不出內容豐富的文章

但這篇要介紹的是 NHibernate 3.2 內建的Mapping By Code,將過去資料庫與類別

對應的xml改為到cs檔裡面撰寫,除了有強型別好處外,也可讓開發人員

更容易設計自己的類別。

 

本篇利用ASP.NET MVC + NHibernate 3.2 實作

資料庫選用SQLite,並利用Code First在執行時期建立出資料庫

由於網路上目前NHibernate與Mapping By Code的中文文章相對的不多,因此會

著重NHibernate這個部分,並簡單的做出一個CRUD的功能。

 

首先建立一個新的ASP.NET MVC 2空白專案,並利用NeGet 抓取NHibernate 3.2 版


搜尋NHibernate,並且安裝


 

安裝好後,開始寫第一個Product類別

Product.cs

01public class Product
02{
03    public virtual int Id { getset; }
04    public virtual string Name { getset; }
05    public virtual int Price { getset; }
06    public virtual int Quantity { getset; }
07    public virtual int CreateUserId { getset; }
08    public virtual DateTime CreateTime { getset; }
09    public virtual int? EditUserId { getset; }
10    public virtual DateTime? EditTime { getset; }
11}

注意!!所有成員都必須是virtual。

這個實體類別就是我們在程式中所使用的Product類別,我們可以依實際的需要設計這個類別

接著寫Product類跟資料庫要如何對應的ProductMapping類別

ProductMapping.cs

01using System;
02using NHibernate.Mapping.ByCode.Conformist;
03using NHibernate.Mapping.ByCode;
04 
05namespace NHibernateMappingByCode.Models.Mapping
06{
07    //繼承ClassMapping<T>
08    public class ProductMapping : ClassMapping<Product>
09    {
10        public ProductMapping()
11        {
12            /* 如果是共用的屬性可以自訂一個父類別去Mapping
13             * 就可以不用每個類別都寫重複的對應       
14             */
15            //主鍵,產生的類型選擇Identity
16            Id(p => p.Id, map => map.Generator(Generators.Identity));
17            Property(p => p.CreateTime, map => map.NotNullable(true));
18            Property(p => p.CreateUserId, map => map.NotNullable(true));
19            Property(p => p.EditTime);
20            Property(p => p.EditUserId);
21 
22            Property(p => p.Name, map => { map.Length(50); map.NotNullable(true); });
23            Property(p => p.Price, map => map.NotNullable(true));
24            Property(p => p.Quantity, map => map.NotNullable(true));
25        }
26    }
27}

這邊採用的是Conformist Mapping,另外還有一種方式是下面這種Specific Mapper,就不介紹了。

1var mapper = new ModelMapper();
2mapper.Class<TestClass>(cm =>
3{
4    cm.Id(p => p.Id, map => map.Generator(Generators.Identity));
5    cm.Property(p => p.Something);
6});

關於Mapping的設定還有非常多,像一對多、多對一、多對多、Cache等..設定

等研究透徹一點後再慢慢分享出來。

寫完了我們的實體類別跟對應之後,接著就來設定連線

NHibernateUtility.cs

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Web;
05using NHibernate.Cfg;
06using NHibernate;
07using NHibernate.Dialect;
08using System.Data;
09using NHibernate.Cfg.MappingSchema;
10using NHibernate.Mapping.ByCode;
11using System.Reflection;
12using NHibernateMappingByCode.Models.Mapping;
13 
14namespace NHibernateMappingByCode.Models
15{
16    public class NHibernateUtility
17    {
18        public static Configuration Configuration { getprivate set; }
19 
20        public static ISessionFactory SessionFactory { getprivate set; }
21 
22        public void Initialize()
23        {
24            Configuration = Configure();
25 
26            SessionFactory = Configuration.BuildSessionFactory();
27        }
28 
29        private Configuration Configure()
30        {
31            var configuration = new Configuration();
32 
33            // 資料庫設定
34            // 這裡的東西可以改用xml的方式設定,增加修改的彈性
35            configuration.DataBaseIntegration(c =>
36            {
37                // 資料庫選用 SQLite
38                c.Dialect<SQLiteDialect>();
39                // 取用 .config 中的 "MyTestDB" 連線字串
40                c.ConnectionStringName = "MyTestDB";
41                // Schema 變更時的處置方式
42                c.SchemaAction = SchemaAutoAction.Update;
43                // 交易隔離等級
44                c.IsolationLevel = IsolationLevel.ReadCommitted;
45            });
46 
47            // 取得Mapping
48            // 取代舊有的 *.hbm.xml
49            var mapping = GetMappings();
50 
51            //加入Mapping
52            configuration.AddMapping(mapping);
53 
54            return configuration;
55        }
56 
57        private HbmMapping GetMappings()
58        {
59            var mapper = new ModelMapper();
60 
61            //加入Mapping
62            //如果是多個 Type 可用 AddMappings
63            mapper.AddMapping(typeof(ProductMapping));
64 
65            HbmMapping mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
66            return mapping;
67        }
68    }
69}

Configuration就是以往NHibernate設置在hibernate.cfg.xml的連線設定

當然設定在xml中修改後不需要重新編譯,使用上較方便,但這邊介紹的是另外一種寫法。

 

由於是Code First,因此在開發時完全不需要考慮到資料庫,這是讓我覺得Code First最

棒的一點,如果需要更換資料庫的話,只需要更改上方的

1//c.Dialect<SQLiteDialect>();
2//更換成使用 SQL 2008
3c.Dialect<MsSql2008Dialect>();

並將連線字串改為SQL 2008資料庫的設定,在Application重啟時,就會在對應的資料庫

中生成Table。

 

接著在Global.asax.cs中,Application_Start()時加入

1protected void Application_Start()
2{
3    NHibernateUtility utility = new NHibernateUtility();
4    utility.Initialize();
5 
6    AreaRegistration.RegisterAllAreas();
7 
8    RegisterRoutes(RouteTable.Routes);
9}

然後運行時就會把Table建出來了。

另外還有一點要注意的是,這邊SchemaActoin設定是Update

也就是Product類別與ProductMapping對應有改變時,就會Update資料庫的Schema

當系統上線後,不妨把這一行拿掉,以免不小心被誰改到了結果資料庫整個亂掉

 

到這邊為止我們已經有了一張Product Table

為了讓範例完整一點,就寫一個ProductService做出CRUD的功能

(這邊沒有特別去管理Session與實作Repository,因此僅供參考就好)

ProductService.cs

001using System;
002using System.Collections.Generic;
003using System.Linq;
004using System.Web;
005using NHibernate;
006using NHibernate.Linq;
007 
008namespace NHibernateMappingByCode.Models
009{
010    public class ProductService
011    {
012        public IEnumerable<Product> GetAll()
013        {
014            IEnumerable<Product> model;
015            using (var session = NHibernateUtility.SessionFactory.OpenSession())
016            {
017                model = session.Query<Product>().ToList();
018            }
019            return model;
020        }
021 
022        public Product GetSingle(int id)
023        {
024            Product model;
025            using (var session = NHibernateUtility.SessionFactory.OpenSession())
026            {
027                model = session.Get<Product>(id);
028            }
029            return model;
030        }
031 
032        public void Insert(Product model)
033        {
034            model.CreateTime = DateTime.Now;
035            model.CreateUserId = 1;
036 
037            //如同時處理好幾張表,可加入交易避免例外發生時產生髒資料
038            using (var session = NHibernateUtility.SessionFactory.OpenSession())
039            using (var trans = session.BeginTransaction())
040            {
041                try
042                {
043                    session.Save(model);
044                    trans.Commit();
045                }
046                catch (Exception ex)
047                {
048                    // Log...
049                    trans.Rollback();
050                }
051            }
052        }
053 
054        public void Update(int id, Product model)
055        {
056             var soucre = GetSingle(id);
057 
058             if (soucre != null)
059             {
060                 soucre.Name = model.Name;
061                 soucre.Price = model.Price;
062                 soucre.Quantity = model.Quantity;
063                 soucre.EditTime = DateTime.Now;
064                 soucre.EditUserId = 1;
065 
066                 //如同時處理好幾張表,可加入交易避免例外發生時產生髒資料
067                 using (var session = NHibernateUtility.SessionFactory.OpenSession())
068                 using (var trans = session.BeginTransaction())
069                 {
070                     try
071                     {
072                         session.SaveOrUpdate(soucre);
073                         trans.Commit();
074                     }
075                     catch (Exception ex)
076                     {
077                         // Log...
078                         trans.Rollback();
079                     }
080                 }
081             }
082        }
083 
084        public void Delete(int id)
085        {
086            var model = GetSingle(id);
087 
088            if (model != null)
089            {
090                using (var session = NHibernateUtility.SessionFactory.OpenSession())
091                using (var trans = session.BeginTransaction())
092                {
093                    try
094                    {
095                        session.Delete(model);
096                        trans.Commit();
097                    }
098                    catch (Exception ex)
099                    {
100                        // Log...
101                        trans.Rollback();
102                    }
103                }
104            }
105        }
106    }
107}

HomeController.cs

01namespace NHibernateMappingByCode.Controllers
02{
03    public class HomeController : Controller
04    {
05        ProductService _prodcutService;
06 
07        public HomeController()
08        {
09            _prodcutService = new ProductService();
10        }
11 
12        public ActionResult Index()
13        {
14            var model = _prodcutService.GetAll();
15            return View(model);
16        }
17 
18        public ActionResult Insert()
19        {
20            return View();
21        }
22 
23        [HttpPost]
24        public ActionResult Insert(Product model)
25        {
26            _prodcutService.Insert(model);
27            return RedirectToAction("Index");
28        }
29 
30        public ActionResult Update(int id)
31        {
32            var model = _prodcutService.GetSingle(id);
33            return View(model);
34        }
35 
36        [HttpPost]
37        public ActionResult Update(int id, Product model)
38        {
39            _prodcutService.Update(id, model);
40            return RedirectToAction("Index");
41        }
42 
43        public ActionResult Delete(int id)
44        {
45            _prodcutService.Delete(id);
46            return RedirectToAction("Index");
47        }
48    }
49}

 

 


0 0