NHibernate学习
紧接上篇博文继续学习(PS:很多代码我就不重复了,在上篇博文的基础上开始学习NHibernate吧~)
代码还是像往常一样在Word里面总结了,这里就直接Copy,Copy
建立IRepository接口(注意引入程序集NHibernate)
public interface IRepository<T> { void Add(T objectToAdd); void AddList(IList<T> list); void Delete(T objectToDelete); void DeleteList(IList<T> list); void Update(T objectToUpdate); void UpdateList(IList<T> list); IQueryable<T> Query(); ISQLQuery DTOQuery(string command); /// <summary> /// 返回特定的数据 和当前的Repository中对象可以不一致 P SQLQuery<P>(string command); }
建立Repository类
public class Repository<T> : IRepository<T> { public ISessionFactory sessionFactory { get; set; } /// <summary> /// 增加一个实体 /// </summary> /// <param name="objectToAdd"></param> public void Add(T objectToAdd) { ISession session = GetSession(); session.Save(objectToAdd); session.Flush(); } /// <summary> /// 增加多条实体 /// </summary> /// <param name="list"></param> public void AddList(IList<T> list) { if (list==null||list.Count==0) { return; } var session = GetSession(); using (var tran = session.BeginTransaction()) { foreach (var item in list) { session.Save(item); } tran.Commit(); } } /// <summary> /// 删除一条实体 /// </summary> /// <param name="objectToDelete"></param> public void Delete(T objectToDelete) { ISession session = GetSession(); session.Delete(objectToDelete); session.Flush(); } /// <summary> /// 删除多条实体 /// </summary> /// <param name="list"></param> public void DeleteList(IList<T> list) { if (list==null||list.Count==0) { return; } var session = GetSession(); using (var tran=session.BeginTransaction()) { foreach (var item in list) { session.Delete(item); } tran.Commit(); } } /// <summary> /// 更新一个实体 /// </summary> /// <param name="objectToUpdate"></param> public void Update(T objectToUpdate) { ISession session = GetSession(); session.SaveOrUpdate(objectToUpdate); session.Flush(); } /// <summary> /// 更新多条实体 /// </summary> /// <param name="list"></param> public void UpdateList(IList<T> list) { if (list == null || list.Count == 0) { return; } var session = GetSession(); using (var tran = session.BeginTransaction()) { foreach (var item in list) { session.Update(item); } tran.Commit(); } } /// <summary> /// 查询一条SQL语句 /// </summary> /// <param name="command"></param> /// <returns></returns> public ISQLQuery DTOQuery(string command) { ISession session = GetSession(); var query = session.CreateSQLQuery(command); query.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean(typeof(T))); return query; } /// <summary> /// 查询所有的数据 /// </summary> /// <returns></returns> public IQueryable<T> Query() { ISession session = GetSession(); return session.Query<T>(); } /// <summary> /// 查询总量 /// </summary> /// <typeparam name="P"></typeparam> /// <param name="command"></param> /// <returns></returns> public P SQLQuery<P>(string command) { P result; ISession session = GetSession(); var query = session.CreateSQLQuery(command); result = query.UniqueResult<P>(); return result; } /// <summary> /// NHibernate中获取Session /// </summary> /// <returns></returns> protected virtual ISession GetSession() { ISession session = this.sessionFactory.GetCurrentSession(); if (session==null) { session = this.sessionFactory.OpenSession(); } return session; } } /// <summary> /// ISession的扩展方法 /// </summary> public static class ExpandClass { public static IQueryable<T> Query<T>(this ISession session) { return new NhQueryable<T>(session.GetSessionImplementation()); } }
写IWindsorInstaller继承类(PS:需要引入的程序集有:Castle.Windsor.Lifestyles和FluentNHibernate)
public class NHibernateInstaller: IWindsorInstaller { public string SQL = ConfigurationManager.ConnectionStrings["SQL"].ConnectionString; public void Install(IWindsorContainer container, IConfigurationStore store) { //将IRepository和Repository关联 container.Register(Component.For(typeof(IRepository<>)) .ImplementedBy(typeof(Repository<>)) .LifeStyle.HybridPerWebRequestTransient() ); container.Register(Component.For<ISessionFactory>() .UsingFactoryMethod(k => BuildSessionFactory(SQL)) ); } public ISessionFactory BuildSessionFactory(string factoryKey) { var config = Fluently.Configure() .Database ( MsSqlConfiguration.MsSql2008.DefaultSchema("dbo").ConnectionString(factoryKey) .ShowSql() ) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<GoodsClassifyEntity>()) //将Mapping文件注入,这个实体类随便写一个就行了 .CurrentSessionContext(typeof(LazySessionContext).AssemblyQualifiedName ); var sessionFactory = config.BuildSessionFactory(); return sessionFactory; } }
上面用到一个LazySessionContext类
public class LazySessionContext : ICurrentSessionContext { private readonly ISessionFactoryImplementor factory; private const string CurrentSessionContextKey = "NHibernateCurrentSession"; public LazySessionContext(ISessionFactoryImplementor factory) { this.factory = factory; } /// <summary> /// Retrieve the current session for the session factory. /// </summary> /// <returns></returns> public ISession CurrentSession() { Lazy<ISession> initializer; var currentSessionFactoryMap = GetCurrentFactoryMap(); if (currentSessionFactoryMap == null || !currentSessionFactoryMap.TryGetValue(factory, out initializer)) { return null; } return initializer.Value; } /// <summary> /// Bind a new sessionInitializer to the context of the sessionFactory. /// </summary> /// <param name="sessionInitializer"></param> /// <param name="sessionFactory"></param> public static void Bind(Lazy<ISession> sessionInitializer, ISessionFactory sessionFactory) { var map = GetCurrentFactoryMap(); map[sessionFactory] = sessionInitializer; } /// <summary> /// Unbind the current session of the session factory. /// </summary> /// <param name="sessionFactory"></param> /// <returns></returns> public static ISession UnBind(ISessionFactory sessionFactory) { var map = GetCurrentFactoryMap(); var sessionInitializer = map[sessionFactory]; map[sessionFactory] = null; if (sessionInitializer == null || !sessionInitializer.IsValueCreated) return null; return sessionInitializer.Value; } /// <summary> /// Provides the CurrentMap of SessionFactories. /// If there is no map create/store and return a new one. /// </summary> /// <returns></returns> private static IDictionary<ISessionFactory, Lazy<ISession>> GetCurrentFactoryMap() { IDictionary<ISessionFactory, Lazy<ISession>> currentFactoryMap = null; if (HttpContext.Current != null) { currentFactoryMap = (IDictionary<ISessionFactory, Lazy<ISession>>) HttpContext.Current.Items[CurrentSessionContextKey]; if (currentFactoryMap == null) { currentFactoryMap = new Dictionary<ISessionFactory, Lazy<ISession>>(); HttpContext.Current.Items[CurrentSessionContextKey] = currentFactoryMap; } } else //为了application Job 执行,由于Job执行时没有HttpContext.Current { if (CurrentFactoryMap == null) { CurrentFactoryMap = new Dictionary<ISessionFactory, Lazy<ISession>>(); } currentFactoryMap = CurrentFactoryMap; } return currentFactoryMap; } private static IDictionary<ISessionFactory, Lazy<ISession>> CurrentFactoryMap; }
数据库连接配置:
<add name="SQL" connectionString="server=.;database=MyTry;integrated security=true;"/>
NHibernate映射需要写一个实体类和一个映射文件,不写映射的话,就只能用SQL语句查询,而不能使用NHibernate查,所以我们先搭建一个映射,让实体和表关联,
下面就介绍下Goods表和GoodsClassify表在NHibernate中的使用:
Goods实体文件:
[Serializable] public class GoodsEntity { public virtual int ID { get; set; } public virtual string GoodName { get; set; } public virtual int ClassID { get; set; } public virtual DateTime? CreateTime { get; set; } }
Goods映射文件:
public class GoodsMap:ClassMap<GoodsEntity> { public GoodsMap() { Table("Goods"); Id(x => x.ID).GeneratedBy.Assigned(); Map(x => x.GoodName); Map(x => x.ClassID); Map(x => x.CreateTime); } }
GoodsClassify实体文件:
[Serializable] public class GoodsClassifyEntity { public virtual int ClassID { get; set; } public virtual string CategoryName { get; set; } public virtual DateTime? CreateTime { get; set; } }
GoodsClassify映射文件:
public class GoodsClassifyMap : ClassMap<GoodsClassifyEntity> { public GoodsClassifyMap() { Table("GoodsClassify"); Id(x => x.ClassID).GeneratedBy.Assigned(); Map(x=>x.CategoryName); Map(x=>x.CreateTime); } }
以上是连接单个数据库,我们还可以设置连接多个数据库:
1>.首先新建一个Repository子类TestRepository继承Repository并重写GetSession
public class TestRepository<T>:Repository<T> { string key = "TestConnection";//这个注入的啥获取的时候Key就是啥 protected override ISession GetSession() { ISessionFactory factory = IocContainer.Container.Resolve<ISessionFactory>(key); ISession session=factory.GetCurrentSession(); if (session==null) { session = factory.OpenSession(); } return session; } }
2.>在NHIbernate内注入其它数据库,修改下NHibernateInstaller类
public class NHibernateInstaller: IWindsorInstaller { public string MyTry="MyTryConnection"; public string Test = "TestConnection"; public void Install(IWindsorContainer container, IConfigurationStore store) { //将IRepository和Repository关联 container.Register(Component.For(typeof(IRepository<>)) .ImplementedBy(typeof(Repository<>)) .LifeStyle.HybridPerWebRequestTransient() ); container.Register(Component.For<ISessionFactory>() .UsingFactoryMethod(k => BuildSessionFactory(MyTry))); //将其它数据库进行注入,别忘了结尾加Named container.Register(Component.For<ISessionFactory>() .UsingFactoryMethod(k => BuildSessionFactory(Test)).Named(Test)); } public ISessionFactory BuildSessionFactory(string factoryKey) { var con = ConfigurationManager.ConnectionStrings[factoryKey]; var config = Fluently.Configure() .Database ( MsSqlConfiguration.MsSql2008.DefaultSchema("dbo").ConnectionString(con.ConnectionString) .ShowSql() ) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<GoodsEntity>()) //将Mapping文件注入 .CurrentSessionContext(typeof(LazySessionContext). AssemblyQualifiedName ); var sessionFactory = config.BuildSessionFactory(); return sessionFactory; } }
3>.将TargetInstall类去掉,添加IocContainer自定义容器类
public class IocContainer { private const string Interceptors = "Demo2.ServiceInterceptor"; private static IWindsorContainer container; public static IWindsorContainer Container { get { if (container==null) { container = new WindsorContainer(); container.Register(Classes.FromThisAssembly() //在哪里找寻接口或类 .BasedOn<IController>() //实现IController接口 .If(Component.IsInSameNamespaceAs<HomeController>()) //与HomeController在同一个命名空间 .If(t => t.Name.EndsWith("Controller")) //以"Controller"结尾 .Configure(c => c.LifestylePerWebRequest()));//每次请求创建一个Controller实例 var componentList = new List<IRegistration>(); var classes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsVisible).Where(p => ((ServiceAttribute)p.GetCustomAttributes(typeof(ServiceAttribute), false).FirstOrDefault()) != null).ToList(); foreach (var item in classes) { var name = item.FullName; var baseType = ((ServiceAttribute)item.GetCustomAttributes(typeof(ServiceAttribute), false).First()).BaseType; componentList.Add(Component.For(baseType).ImplementedBy(item).Named(name).Interceptors(Interceptors)); } container.Register(componentList.ToArray()); } return container; } } }
4>.在Global修改如下
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); BootstrapContainer(); } public IWindsorContainer Container { get { return IocContainer.Container; } } private void BootstrapContainer() { //初始化一个IOC容器 Container.Install(FromAssembly.This()); //完成IWindsorInstaller接口中的注册 ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container.Kernel)); } }
5>.在Goods里面进行调用
[Service(BaseType =typeof(IGoods))] public class Goods : IGoods { rivate IRepository<GoodsEntity> repository; IRepository<UsersEntity> usersRepository;//其余数据库创建对象,直接new即可。注意里面填写的UsersEntity实体是否和方法获取的实体对应 public Goods(IRepository<GoodsEntity> repository) //声明对象 { this.repository = repository; this.usersRepository = new TestRepository<UsersEntity>(); } //测试方法 public List<string> GetUserName(int id) { List<string> list = new List<string>(); var model= usersRepository.Query().FirstOrDefault(c=>c.UserID==id); var model2 = repository.Query().FirstOrDefault(c=>c.ID==id); if (model != null) { list.Add(model.UserName); list.Add(model2.GoodName); } return list; } }
好了,NHibernate大概就这么多了。
百闻不如一见,百见不如一做,只有做了,才知道问题出现在哪儿,才能去解决问题。