zoukankan      html  css  js  c++  java
  • NHibernate 映射基础(第三篇) 简单映射、联合主键

      NHibernate完全靠配置文件获取其所需的一切信息,其中映射文件,是其获取数据库与C#程序关系的所有信息来源。

    一、简单映射

      下面先来一个简单的例子,然后随着不断地对这个例子修修改改,从而真正了解映射文件。具体的资料可以查看http://www.cnblogs.com/kissdodog/archive/2013/02/21/2919886.html

      先来看一张表:

      

      映射文件Product.hbm.xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class name="Model.ProductModel, Model" table="Product">
        <id name="ProductId" column="ProductId" type="Int32">
          <generator  class="native"/>
        </id>
        <property name="ProductName" column="ProductName" type="String"/>
        <property name="ProductPrice" column="ProductPrice" type="float"/>
        <property name="ProductDiscount" column="ProductDiscount" type="float"/>
        <!--这个属性没有与之对应的列,其列为ProductPrice * ProductDiscount相乘得来-->
        <property name="ActualPrice" formula="ProductPrice * ProductDiscount" type="float"/>
      </class>
    </hibernate-mapping>

      PersonModel.cs:

    namespace Model
    {
        public class ProductModel
        {
            public virtual int ProductId { get; set; }
            public virtual string ProductName { get; set; }
            public virtual float ProductPrice { get; set; }
            public virtual float ProductDiscount { get; set; }
            public virtual float ActualPrice { get; set; }  //数据库里并没有这个字段
        }
    }

      在这里要注意下最后一个字段,数据库里并没有这个字段。

      ProductDao.cs:

        public class ProductDao
        {
            public ProductModel GetProduct(int Id)
            {
                ISession NSession = NHibernateHelper.GetSession();
                return NSession.Get<ProductModel>(Id);
            }
        }

      Program.cs:

            static void Main(string[] args)
            {
                ProductDao dao = new ProductDao();
                ProductModel pm = dao.GetProduct(1);
                Console.WriteLine(pm.ProductId + " " + pm.ProductName + " " + pm.ProductPrice + " " + pm.ProductDiscount + " " + pm.ActualPrice);
            }

      显示结果如下:

      

      你可能奇怪,为什么最后一个字段数据库没有,但是为什么也能够查询出结果呢?答案在于配置里面的

      formula="ProductPrice * ProductDiscount"

      这个属性配置之后,允许某字段的值从其他字段计算获得。

      我们来看看生成的SQL代码

    exec sp_executesql N'SELECT productmod0_.ProductId as ProductId4_0_, productmod0_.ProductName as ProductN2_4_0_, productmod0_.ProductPrice as ProductP3_4_0_, 
    productmod0_.ProductDiscount as ProductD4_4_0_, productmod0_.ProductPrice * productmod0_.ProductDiscount as formula0_0_ FROM Product productmod0_ WHERE productmod0_.ProductId=@p0',N'@p0 
    int',@p0=1
    --以上SQL代码相当于
    SELECT ProductId,ProductName,ProductPrice,ProductDiscount, ProductPrice * ProductDiscount AS formula FROM Product

      其实,这是NHibernate根据我们的配置,帮我们生成了SQL语句,计算出另外的字段并绑定的对应的属性当中。

      下面我们开始来不断更改,以了解更多的NHibernate配置的作用。

      我们将Product.hbm.xml的第一行加上下面这一句:

      select-before-update="true"
     <class name="Model.ProductModel, Model" table="Product" select-before-update="true">

      然后PersonDao.cs增加此方法:

            public void UpdateProduct(ProductModel product)
            {
                ISession NSession = NHibernateHelper.GetSession();
                NSession.Update(product);
                NSession.Flush();
            }

      用于更新一个Product。

      Program.cs:

            static void Main(string[] args)
            {
                ProductDao dao = new ProductDao();
                ProductModel pm = dao.GetProduct(1);
                dao.UpdateProduct(pm);
            }

      对于此操作,SQL Server Profiler检测到执行了如下语句:

    exec sp_executesql N'SELECT productmod0_.ProductId as ProductId4_0_, productmod0_.ProductName as ProductN2_4_0_, productmod0_.ProductPrice as ProductP3_4_0_, 
    productmod0_.ProductDiscount as ProductD4_4_0_, productmod0_.ProductPrice * productmod0_.ProductDiscount as formula0_0_ FROM Product productmod0_ WHERE productmod0_.ProductId=@p0',N'@p0 
    int',@p0=1
    --相当于如下语句
    SELECT ProductId,ProductName,ProductPrice,ProductDiscount FROM Product WHERE ProductId = 1

      而当我们去掉

      select-before-update  
      或者将其值设置为flase时,就会直接执行UPDATE语句。select-before-update的作用在于,控制在UPDATE语句之前是否先执行一次查询,以检查对象是否有变化,当数据发生变化之后才UPDATE,否则不UPDATE。

    二、联合主键

      新建一张表如下:

         

       以上3列数据都是NVarchar()类型。

      下面来看配置映射文件:

      Composite.hbm.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class name="Model.CompositeModel, Model" table="Composite">
        <composite-id name="Pk" class="Model.PKModel, Model">  //name为主实体类的属性名
            <key-property name="Id1" type="String" column="Id1"/>
            <key-property name="Id2" type="String" column="Id2"/>
        </composite-id>
        <property name="Name" column="Name" type="String"/>
      </class>
    </hibernate-mapping>

      CompositeModel.cs

        public class CompositeModel
        {
            public virtual PKModel Pk { get; set; }
            public virtual string Name { get; set; }
        }

      PKModel.cs

        public class PKModel
        {
            public virtual string Id1 { get; set; }
            public virtual string Id2 { get; set; }
    
            /// <summary>
            /// 判断两个对象是否相同,这个方法需要重写
            /// </summary>
            /// <param name="obj">进行比较的对象</param>
            /// <returns>真true或假false</returns>
            public override bool Equals(object obj)
            {
                if (obj is PKModel)
                {
                    PKModel pk = obj as PKModel;
                    if (this.Id1 == pk.Id1 && this.Id2 == pk.Id2)
                    {
                        return true;
                    }
                }
                return false;
            }
    
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }

       操作:

       class Program
        {
            static void Main(string[] args)
            {
                ISessionFactory _sessionFactory = new Configuration().Configure().BuildSessionFactory();
                using(ISession NSession = _sessionFactory.OpenSession())
                {
                    IList<CompositeModel> ListComposite = NSession.Query<CompositeModel>().ToList();
                    foreach (var c in ListComposite)
                    {
                        Console.WriteLine(c.Name);
                    }
    
                    //查询单条
                    PKModel pk = new PKModel();
                    pk.Id1 = "01";
                    pk.Id2 = "1";
                    CompositeModel m = NSession.Get<CompositeModel>(pk);
                    Console.WriteLine(m.Name);
                }
                Console.ReadKey();
            }
        }

      输出:

       

       要点:1、联合主键提取出来作为一个类

          2、要重写两个方法

  • 相关阅读:
    Mvc分页:为IQueryable定义一个扩展方法,直接反回PagedList<T>结果集
    从零开始一起学习SLAM | 相机成像模型
    从零开始一起学习SLAM | 为啥需要李群与李代数?
    从零开始一起学习SLAM | 三维空间刚体的旋转
    从零开始一起学习SLAM | 为什么要用齐次坐标?
    从零开始一起学习SLAM | C++新特性要不要学?
    从零开始一起学习SLAM | SLAM有什么用?
    从零开始一起学习SLAM | 学习SLAM到底需要学什么?
    2019年度【计算机视觉&机器学习&人工智能】国际重要会议汇总
    从零开始一起学习SLAM | 为什么要学SLAM?
  • 原文地址:https://www.cnblogs.com/kissdodog/p/2942772.html
Copyright © 2011-2022 走看看