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包。