zoukankan      html  css  js  c++  java
  • 利用NHibernate与MySQL数据库交互

      本文章使用Visual Studio作为开发工具,并建立在已经安装MySQL数据库的前提。

      NHibernate是一个面向.NET环境的对象/关系数据库映射工具。官网:http://nhibernate.info。官网Documentation下,帮助文档The NHibernate Reference (HTML, single page HTML, PDF, CHM),和案例教程Tutorial: Your first NHibernate based application,这两篇文档是我撰写此文章的主要依据。

      NHibernate与MySQL交互原理:写代码调用NHibernate的API,NHibernate则调用MySQL的API从而操作MySQL数据库。

      C#连接MySQL数据库的原理是:写代码调用MySQL的API从而操作MySQL数据库。

      完整解决方案资源管理器参考:

      

    1.添加动态链接库

      (1)添加Nhibernate的动态链接库

      方法一:在 项目(右键)-管理NuGet程序包(N)  然后在浏览里面搜索Nhibernate并进行安装。若安装失败可以选择低一点的版本4.1.1.4000。

      方法二:在NHibernate官网:http://nhibernate.info 里点击Download Now NH5.0.3下载,并将 \Required_Bins\Nhibernate.dll 添加到引用

      (2)添加MySQL的动态链接库

      方法一:在 项目(右键)-管理NuGet程序包(N)  然后在浏览里面搜索MySql.Data并进行安装。

      方法二:安装数据库MySQL时要选中Connector.NET 6.9的安装,将C:\Program Files (x86)\MySQL\Connector.NET 6.9\Assemblies里v4.0或v4.5中的MySql.Data.dll添加到项目的引用。v4.0和v4.5,对应Visual Studio具体项目 属性-应用程序-目标框架 里的.NET Framework的版本号。

    2.NHibernate配置

      (1)配置程序集名称和默认命名空间:。项目(右键)-属性  程序集名称与默认命名空间都改成英文(首字母大写),方便以后调用,以下案例程序集名称和默认命名空间均为UseNhibernate。

      (2)添加hibernate.cfg.xml并进行配置 。直接在 项目(右键)-添加-新建项-XML文件 命名必须为hibernate.cfg.xml,配置文件为(参考案例教程Tutorial: Your first NHibernate based application或者百度NHibernate配置MySQL数据库)

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <session-factory>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="dialect">NHibernate.Dialect.MySQL5Dialect</property><!--配置数据库的dialect -->
        <property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property><!--配置数据库的driver -->
        <property name="connection.connection_string">Server=localhost;Database=minecraftdb;User ID=root;Password=root;</property><!--配置连接数据库的信息-->
    
        <property name="show_sql">true</property>
      </session-factory>
    </hibernate-configuration>
    <!--这个文档的 复制到输出目录 要选择 始终复制 -->

      dialect配置参考: 帮助文档The NHibernate Reference的3.5.1

      NHibernate与各种数据库交互的配置的文件: https://www.cnblogs.com/wdw31210/p/3916252.html

    3.进行类和表的映射

      (1)项目(右键)-添加-新建文件夹Model存放类,每一张表的映射对应一个类,一行数据对应一个实例对象

    以User.cs为例

    namespace UseNhibernate.Model
    {
        public class User
    { 
            public virtual int UserId { get; set; }
            public virtual string UserName { get; set; }
            public virtual string Password { get; set; }
            public virtual DateTime RegisterDate { get; set; } 
        }
    }

      (2)项目(右键)-添加-新建文件夹Mappings存放配置文件,数据库每一张表到类的映射对应一个配置文件

    以User.hbm.xml为例

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="UseNhibernate"
                       namespace="UseNhibernate.Model"><!—映射类的命名空间-->
    
      <class name="User" table="user">
        <id name="UserId" column="userid" type="Int32">
          <generator class="native"></generator>
        </id><!—主键-->
        <property name="UserName" column="username" type="String"></property>
        <property name="Password" column="password" type="String"></property>
        <property name="RegisterDate" column="registerdate" type="Date"></property><!--type类型是nhibernate自己有一套-->
      </class>
    </hibernate-mapping>
    <!--注意这个文档的 生成操作 要选择 ,会打包进.exe文件即程序集-->

      type参考: The NHibernate Reference中的5.2

      (3)直接调用NHibernate的API进行访问数据库(用于了解整个调用过程)

    Configuration configuration = new Configuration();
    configuration.Configure();//解析固定路径下的配置文件 hibernate.cfg.xml(默认命名)// configuration.Configure(“myhibernate.cfg.xml”);
    configuration.AddAssembly("UseNhibernate");//加载程序集UseNhibernate下的所有映射文件如User.hbm.xml(这个文档的生成操作要选择嵌入的资源,会打包进.exe文件即程序集)//解析配置的几种方式在The NHibernate Reference的3.1
    
    ISessionFactory sessionFactory = null;
    ISession session = null;
    ITransaction transaction = null;
    
    try
    {
      sessionFactory = configuration.BuildSessionFactory();
      session = sessionFactory.OpenSession();//打开一个跟数据库的会话session,对数据库的操作都是通过session实现
    
      //1.单条语句执行数据库操作
      //User user = new User() { UserName = "小红",Password="123",RegisterDate=DateTime.Now };
      //session.Save(user);
    
      //2.事务执行数据库操作,利用事务执行多条操作语句,只要有一条不成功就都不成功
      transaction = session.BeginTransaction();
    
      User user1 = new User() { UserName = "小红", Password = "123", RegisterDate = DateTime.Now };
      User user2 = new User() { UserName = "小黄", Password = "123", RegisterDate = DateTime.Now };
      session.Save(user1);
      session.Save(user2);
    }
    catch (HibernateException e)
    {
      Console.WriteLine(e.InnerException.Message);
      transaction.Rollback();
    }
    finally {
      if(!transaction.WasRolledBack)
      {
        transaction.Commit();
      }
      if (transaction != null)   {     transaction.Dispose();   }   if (session != null)   {     session.Close();   }   if (sessionFactory != null)   {     sessionFactory.Close();   } }

      不推荐这么直接访问数据库,要进一步封装:将session操作前的语句都封装成NHibernateHelper、每一个类/张表的增删查改都封装一个管理类

      (4)对于session的操作

      a.增删改

      session.Save(user);将对象user存进数据库对应的表里

      session.Update(user);更新id相同的user对象,对应user对象的id。更新操作必须通过事务才能执行

      session.Delete(user);删除id相同的user对象,定义的user有id就行

      b.查询

      参考The NHibernate Reference中的9.3.Querying和15. Criteria Queries

      User user=session.Get<User>(id);//简单的主键查询

      User user = session.CreateCriteria<User>().Add(Expression.Eq("UserName", username)).Add(Expression.Eq("Password",password)).UniqueResult<User>();//复杂查询,"UserName"是映射类的字段名

      如果查询不到,即数据库没有对应的这一行,则返回null,即user=null   

      c.查询结果的数量

      .UniqueResult<User>();得到一个结果

      .List<User>();得到所有结果

      .SetMaxResults(50).List<User>();得到50个结果

      (5)事务

      利用事务执行一条或多条操作语句,只要有一条不成功就都不成功。常用语句:

      transaction.Commit();提交事务

      transaction.Dispose();关闭事务并释放资源

      transaction.WasRolledBack;事务是否回滚

    using (ITransaction transaction=session.BeginTransaction())
    {
      //执行操作代码
      transaction.Commit();
    } 

      (6)异常的处理

      NHibernate使用可能导致异常,通常是HibernateException。这个异常可以嵌套内部异常(根源),使用InnerException属性来访问它。

    catch (HibernateException e)
    {
      Console.WriteLine(e.InnerException.Message);
      transaction.Rollback();
    }

      (7)进一步封装
      将session操作前的语句都封装成NHibernateHelper、每一个类/张表的增删查改都封装一个管理类

      a.添加NHibernateHelper.cs

    namespace UseNhibernate
    {
        class NHibernateHelper
        {
            private static ISessionFactory _sessionFactory;
    
            public static ISessionFactory SessionFactory
            {
                get
                {
                    if (_sessionFactory == null)
                    {
                        Configuration configuration = new Configuration();
                        configuration.Configure();
                        configuration.AddAssembly("UseNhibernate");
    
                        _sessionFactory = configuration.BuildSessionFactory();
                    }
                    return _sessionFactory;
                }
            }
    
            public static ISession OpenSession()
            {
                return SessionFactory.OpenSession();
            }
        }
    }

      b.项目(右键)-添加-新建文件夹Manager存放IUserManager.cs和UserManager.cs

      IUserManager.cs

    namespace UseNhibernate.Manager
    {
        interface IUserManager
        {
            void Add(User user);
            void Update(User user);
            void Remove(User user);
            User GetById(int id);
            User GetByName(string username);
            IList<User> GetAllUser();
            bool Vertify(string username, string password);
        }
    }

      UserManager.cs

    using System.Collections.Generic;
    using MyGameServer.Model;
    using NHibernate;
    using NHibernate.Criterion;


    namespace
    UseNhibernate.Manager { class UserManager : IUserManager { public void Add(User user) { //1.直接写 //ISession session = NHibernateHelper.OpenSession(); //session.Save(user); //session.Close(); //2.使用using,只要离开了这个代码段就自动调用这个类实例的Dispose,关闭并释放资源 using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction=session.BeginTransaction()) { session.Save(user); transaction.Commit(); } } } public IList<User> GetAllUser() { using (ISession session = NHibernateHelper.OpenSession()) { IList<User> users=session.CreateCriteria<User>().List<User>(); return users; } } public User GetById(int id) { using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { User user=session.Get<User>(id); transaction.Commit(); return user; } } } public User GetByName(string username) { using (ISession session=NHibernateHelper.OpenSession()) { //ICriteria criteria=session.CreateCriteria(typeof(User)); //criteria.Add(Restrictions.Eq("UserName",name)); //User user=criteria.UniqueResult<User>(); User user=session.CreateCriteria<User>().Add(Expression.Eq("UserName", username)).UniqueResult<User>(); return user; } } public void Remove(User user) { using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { session.Delete(user); transaction.Commit(); } } } public void Update(User user) { using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { session.Update(user); transaction.Commit(); } } } public bool Vertify(string username, string password) { using (ISession session=NHibernateHelper.OpenSession()) { User user = session.CreateCriteria<User>() .Add(Expression.Eq("UserName", username)) .Add(Expression.Eq("Password",password)) .UniqueResult<User>(); if (user == null) { return false; } return true; } } } }

       Program.cs

    //User user = new User() { UserName = "怪我咯", Password = "123", RegisterDate = DateTime.Now };
                //IUserManager userManager = new UserManager();
                //userManager.Add(user);
    
                //User user = new User() { UserId=16,UserName = "小白", Password = "123", RegisterDate = DateTime.Now };
                //IUserManager userManager = new UserManager();
                //userManager.Update(user);
    
                //User user = new User() { UserId = 16};
                //IUserManager userManager = new UserManager();
                //userManager.Remove(user);
    
                //IUserManager userManager = new UserManager();
                //User user = userManager.GetById(7);
                //Console.WriteLine(user.UserName + " " + user.Password);
    
                //IUserManager userManager = new UserManager();
                //User user = userManager.GetByName("甘道夫");
                //Console.WriteLine(user.UserName + " " + user.Password);
    
                //IUserManager userManager = new UserManager();
                //IList<User> users = userManager.GetAllUser();
                //foreach (User user in users)
                //{
                //    Console.WriteLine(user.UserName + " " + user.Password);
                //}
    
                IUserManager userManager = new UserManager();
                Console.WriteLine(userManager.Vertify("123", "123"));
    
                Console.ReadKey();

      结语:配置以及映射需要花费些时间,但是后面可以很快捷地对数据库进行各种骚操作。

  • 相关阅读:
    leetcode206题实现反转链表(c语言)
    V22017编写C/C++时没有与参数列表匹配的重载函数实例
    3DMAX导出到Unity坐标轴转换问题
    ihandy2019笔记编程真题
    模糊数学中合成算子的计算方法
    点击Button按钮实现页面跳转
    做HTML静态页面时遇到的问题总结
    pip换源
    Python正课146 —— DRF 进阶7 JWT补充、基于权限的角色控制、django缓存
    Python正课145 —— DRF 进阶6 自定制频率、接口文档、JWT
  • 原文地址:https://www.cnblogs.com/DonYao/p/8446986.html
Copyright © 2011-2022 走看看