1. 程式人生 > >nhibernate的簡單配置與使用

nhibernate的簡單配置與使用

配置nhibernate的方式有兩種,一種是通過xml檔案的方式配置,還有就是通過class的方式配置。網上大多數是以xml的方式配置nhibernate,本文則已class的方式來配置,並通過IOC(依賴注入,本文以構造注入)的方式註冊nhibernate。下面就以一個demo來說明配置、注入以及使用的方法。

建立一個工程,在工程下新增三個專案。
1、Web工程(demo採用的是MVC框架),在專案下新增一個IOC資料夾,並在資料夾下新增一下類,工程圖如圖所示:

這裡寫圖片描述

2、web.Model

這裡寫圖片描述

3、web.Service

這裡寫圖片描述

IOC
a. NHibernateModule.cs —-用於nhibernate的註冊

namespace Web.Ioc.Module
{
    public class NHibernateModule :Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            /* one application have only one ISessionFactory */
            builder.Register(c => new SessionFactoryProvider())
                   .As
<ISessionFactoryProvider>() .SingleInstance(); /* should be instance per http request to ensure one session per request model */ builder.Register(c => new SessionProvider(c.Resolve<ISessionFactoryProvider>())) .As<ISessionProvider>() .InstancePerRequest
(); /* should be instance per http request to ensure one session per request model */ builder.Register(c => new UnitOfWork(c.Resolve<ISessionProvider>())) .As<IUnitOfWork>() /* must be, to commit transaction, to close session, or will lost data and occupied db connection */ //.OnRelease(uow => uow.Close()) // 如果有繼承IDispose介面 則可以不用顯示呼叫 .InstancePerRequest(); } } }

b. ServiceModule.cs —–用於service的註冊

namespace Web.Ioc.Module
{
    public class ServiceModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterGeneric(typeof(Service<>))
                .As(typeof(IService<>))
                .InstancePerRequest();
        }
    }
}

c. IocConfig.cs 用於註冊nhibernate和service

namespace Web.Ioc
{
    public class IocConfig
    {
        public static void Register(/*params Assembly[] contorllerAssemblies*/)
        {
            var builder = new ContainerBuilder();

            builder.RegisterModule(new NHibernateModule());//註冊nhibernate
            builder.RegisterModule(new ServiceModule());//註冊service

            // register controller.
            //註冊Controller。因為框架是採用構造注入的方式
            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            // register api controller
            builder.RegisterApiControllers(typeof(MvcApplication).Assembly);

            // register filters
            // global filters is not working
            builder.RegisterFilterProvider();

            var container = builder.Build();
            // Configure contollers with the dependency resolver
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            // Configure Web API with the dependency resolver
            GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }
    }
}

在Global.asax的Application_Start呼叫Register。如圖:
這裡寫圖片描述

Web.Model:該專案先主要存放資料實體以及實體對應資料庫的對映。即nhibernate的mapping。

demo中的實體類:

namespace Web.Model
{
    public class Barcode : EntityBase
    {
        public Barcode()
        {
            Active = 0;
        }

        public virtual string ItemNumber { get; set; }

        public virtual long LastSerialNbr { get; set; }

        public virtual long MinSerialNbr { get; set; }

        public virtual long MaxSerialNbr { get; set; }

        public virtual int Active { get; set; }

        public virtual int CreatedId { get; set; }

        public virtual DateTime CreatedTime { get; set; }

        public virtual int ModifiedId { get; set; }

        public virtual DateTime ModifiedTime { get; set; }
    }
}

demo中的mapping類:

namespace Web.Model.Mapping
{
    public class BarcodeMapping : EntityBaseMapping<Barcode>
    {
        public BarcodeMapping()
            : base("wp_barcode")
        {
            Property(b => b.ItemNumber, m => m.Column("item_number"));
            Property(b => b.LastSerialNbr, m => m.Column("last_serial_nbr"));
            Property(b => b.MinSerialNbr, m => m.Column("min_serial_nbr"));
            Property(b => b.MaxSerialNbr, m => m.Column("max_serial_nbr"));
            Property(b => b.Active, m => m.Column("active"));
            Property(b => b.CreatedId, m => m.Column("created_id"));
            Property(b => b.CreatedTime, m => m.Column("created_time"));
            Property(b => b.ModifiedId, m => m.Column("modified_id"));
            Property(b => b.ModifiedTime, m => m.Column("modified_time"));
        }
    }
}

Web.Service:—-該模組主要包含用與nhibernate的ISession註冊的類,以及資料庫的互動。主要類:

SessionProvider :獲取nhibernate的session

namespace Web.Service
{
    /// <summary>
    /// wrapping ISesion so that other assembly needn't to reference NHibernate.dll 
    /// </summary>
    public class SessionProvider : ISessionProvider
    {
        private readonly Lazy<ISession> session;

        public ISession Session
        {
            get { return session.Value; }
        }

        public SessionProvider(ISessionFactoryProvider sessionFactoryProvider)
        {
            session = new Lazy<ISession>(() => sessionFactoryProvider.SessionFactory.OpenSession());
        }
    }
}

SessionFactoryProvider :註冊資料庫連線以及mapping

using System.Data;
using System.Reflection;
using System.Linq;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Mapping.ByCode;
using Web.Model.Mapping;


namespace Web.Service
{
    /// <summary>
    /// wrapping ISesionFactory so that other assembly needn't to reference NHibernate.dll 
    /// </summary>
    public class SessionFactoryProvider : ISessionFactoryProvider
    {
        private static readonly ISessionFactory sessionFactory;

        private static Configuration Configuration { get; set; }

        #region ISessionFactoryProvider 成員

        public ISessionFactory SessionFactory
        {
            get { return sessionFactory; }
        }

        #endregion

        static SessionFactoryProvider()
        {

            Configuration = BuildConfiguration();
            sessionFactory = Configuration.BuildSessionFactory();

        }

        //註冊pgsql
        private static Configuration BuildConfiguration()
        {
            var cfg = new Configuration();
            cfg.DataBaseIntegration(db =>
                {
                    db.ConnectionStringName = "pgsqlConn";//對應config中的資料庫連線字串
                    db.Dialect<PostgreSQL82Dialect>();
                    db.Driver<NpgsqlDriver>();
                    db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
                    db.IsolationLevel = IsolationLevel.ReadCommitted;
                    db.BatchSize = 100;
                    db.LogFormattedSql = true;
                    db.AutoCommentSql = true;
#if DEBUG
                    db.LogSqlInConsole = true;
#endif
                });

            cfg.AddMapping(BuildMappings());
            /* Not supported in PostgreSQL */
            //SchemaMetadataUpdater.QuoteTableAndColumns(cfg);

            return cfg;
        }

        /// <summary>
        /// 通過Mapping對映的方式註冊Nhibernate
        /// </summary>
        /// <returns></returns>
        private static HbmMapping BuildMappings()
        {
            var mapper = new ModelMapper();
            mapper.AddMappings(Assembly
                                   .GetAssembly(typeof(TestMapping))//獲取TestMapping所在的程式集,即Web.Model
                                   .GetExportedTypes()
                                   .Where(t => t.Name.EndsWith("Mapping")));
            var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
            return mapping;
        }


        //通過xml的方式註冊nhibernate
//        public static string BuildMappingsXml()
//        {
//            var mapper = new ModelMapper();
//            mapper.AddMappings(Assembly
//                                   .GetAssembly(typeof(UserMapping))
//                                   .GetExportedTypes()
//                                   .Where(t => t.Name.EndsWith("Mapping")));
//            var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
//            return mapping.AsString();
//        }

    }
}

最後呼叫的方式就特別簡單了,在controller中(demo為homeController)


        private readonly IService<Barcode> testService;//宣告物件

        //以建構函式的方式注入
        public HomeController(IService<Barcode> testService)
        {
            this.testService = testService;
        }

        public ActionResult Index()
        {
            List<Barcode> list = testService.Queryable(o => o.Active == 0).ToList();//呼叫service
            return View();
        }

在web.config中新增連線字串:

 <connectionStrings>
    <add name="pgsqlConn" connectionString="Server=xxx.xxx.xx.xx;Port=****;User Id=****;Password=****;Database=****;" /
  </connectionStrings>

demo原始碼:
原始碼

ps:專案採用NuGet管理dll,為防止上傳檔案過大,所有未上傳packages資料夾。下好程式碼後,直接重新生成,即可自動還原NuGet包。