之前介绍了Dapper,速度很快,很轻量,很好用。

但是Dapper其实有自己的弊端,比如在数据关系复杂,数据库表非常多,多数据库支持,数据库结构变动频繁的时候总是很无奈。尽管有代码生成器,但是代码生成器本来就有自身的许多劣根性,比如生成的代码单一,虽然可以用,但是也仅限制在CURD上。把数据库改下了,之前辛苦修改的代码又要重新再改一次,当然这个有方法解决,但是总是带来许多新的问题。

这个也几乎是所有轻量级ORM都会面临的一个问题。

后来实在被这个问题快搞崩溃了,于是写个小工具,希望设计好模型之后,直接生成不同的数据库结构,生成不同的代码表单页面,结果人懒到最后没写完还停在那里,可见这里。

再后来就用上了NHibernate。

NHibernate是一个很强的ORM.尽管让人诟病它的配置项,它的速度,但是亮点也总是很多,甚至超过了java版本。

OK 先来入门。定义几个基础的对象

public class CompanyGroup
    {
        public CompanyGroup() : this(string.Empty) { }

        public CompanyGroup(string name)
        {
            this.CompanyGroupName = name;
        }

        public virtual long CompanyGroupId { get; set; }

        public virtual string CompanyGroupName { get; set; }

        public virtual Company Company { get; set; }

        public virtual DateTime CreateTime { get; set; }

        public virtual CompanyGroupExtend CompanyGroupExtend
        {
            get;
            set;
        }
    }
    /// <summary>
    /// 公司组扩展信息
    /// </summary>
    public class CompanyGroupExtend
    {
        /// <summary>
        /// 扩展信息编号
        /// </summary>
        public virtual long ExtendId { get; set; }

        /// <summary>
        /// 公司组别名
        /// </summary>
        public virtual string CompanyGroupAliases { get; set; }

        /// <summary>
        /// 对应公司组
        /// </summary>
        public virtual CompanyGroup CompanyGroup { get; set; }
    }
public class Company
    {
        public Company()
            : this(null)
        {

        }

        public Company(string name)
        {
            this.CompanyName = name;
            this.CompanyGroups = new List<CompanyGroup>(8);
        }

        public virtual long CompanyId { get; set; }

        public virtual string CompanyName { get; set; }

        public virtual string CompanyDescription { get; set; }

        public virtual DateTime CreateTime { get; set; }

        public virtual ICollection<CompanyGroup> CompanyGroups { get; set; }

        public virtual void AddCompanyGroup(CompanyGroup group)
        {
            if (!this.CompanyGroups.Contains(group))
            {
                this.CompanyGroups.Add(group);

            }
            return;
        }

        public virtual void RemoveCompanyGroup(CompanyGroup group)
        {
            if (this.CompanyGroups.Contains(group))
            {
                this.CompanyGroups.Remove(group);
            }
            return;
        }

    }

几个基础的实体类也反应了一组基础的关于,分别是1:m,和1:1两种管理。

NHibernate3.x之前,需要配置坑爹的xml,这个是个吐槽点,尽管装了xsd能够智能的感知以及修改,但是都忍不住吐槽,看了被c#惯坏了。

在NHibernate3.x以后可以直接进行手动的代码配置。比如

    public class CompanyGroupExtendMap : ClassMapping<CompanyGroupExtend>
    {
        public CompanyGroupExtendMap()
        {
            base.Id(c => c.ExtendId, map =>
            {
                map.Generator(Generators.Foreign<CompanyGroup>(c => c.CompanyGroupExtend));
            });

            base.Property(c => c.CompanyGroupAliases, map =>
            {
                map.Length(50);
                map.NotNullable(true);
            });

            base.OneToOne(c => c.CompanyGroup, map =>
            {
                map.Constrained(true);
                map.Cascade(Cascade.All);
            });
        }
    }
public class CompanyGroupMap : ClassMapping<CompanyGroup>
    {
        public CompanyGroupMap()
        {
            base.Id(c => c.CompanyGroupId, map => { map.Generator(Generators.Native); });
            base.Property(c => c.CompanyGroupName, map => { map.Length(50); map.NotNullable(true); });
            base.Property(c => c.CreateTime, map => map.NotNullable(true));
            base.ManyToOne<Company>(c => c.Company, map =>
            {
                map.Column("CompanyId");
                map.Cascade(Cascade.None);
            });
            base.OneToOne(c => c.CompanyGroupExtend, map =>
            {
                map.Cascade(Cascade.All);
                map.Lazy(LazyRelation.Proxy);
            });
        }
    }
    public class CompanyMap : ClassMapping<Company>
    {
        public CompanyMap()
        {
            base.Id(c => c.CompanyId, map =>
            {
                map.Generator(Generators.Native);
                map.Column("CompanyId");
            });
            base.Property(c => c.CompanyName, map =>
            {
                map.Length(50);
                map.NotNullable(true);
            });

            base.Property(c => c.CreateTime, map =>
            {
                map.NotNullable(true);
            });

            base.Property(c => c.CompanyDescription, map =>
            {
                map.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1);
            });

            base.Set(c => c.CompanyGroups, map =>
            {
                map.Key(r => { r.Column("CompanyId"); });
                map.Cascade(Cascade.All);
                map.Inverse(false);
            }, action => action.OneToMany());
        }
    }

于是通过派生ModelMapper即可实现数据库的生成策略,以及生成数据库对象。

public class DatabaseGenerationStrategyMapper : ModelMapper
    {
        public DatabaseGenerationStrategyMapper()
        {
            //base.BeforeMapClass += (mi, propertyPath, map) => map.Table((propertyPath.Name + "Info").ToLower());
            //base.BeforeMapProperty += (mi, propertyPath, map) => map.Column(propertyPath.ToColumnName().ToLower());
            base.AfterMapManyToOne += (mi, propertyPath, map) =>
            {
                map.Column((propertyPath.LocalMember.Name + "Id"));
                map.ForeignKey(string.Format("FK_{0}_{1}_{2}", propertyPath.LocalMember.Name, propertyPath.LocalMember.DeclaringType.Name, Guid.NewGuid().ToString().Substring(0, 8).ToUpper()));
            };
            base.AfterMapOneToOne += (mi, propertyPath, map) =>
            {
                map.ForeignKey(string.Format("FK_{0}_{1}_{2}", propertyPath.LocalMember.Name, propertyPath.LocalMember.DeclaringType.Name, Guid.NewGuid().ToString().Substring(0, 8).ToUpper()));
            };
        }
    }
public class DatabaseMapper : DatabaseGenerationStrategyMapper
    {
        public DatabaseMapper()
        {
            base.AddMapping<CompanyGroupExtendMap>();
            base.AddMapping<CompanyGroupMap>();
            base.AddMapping<CompanyMap>();
            base.AddMapping<UserMap>();
        }

        public override string ToString()
        {
            return this.CompileMappingForAllExplicitlyAddedEntities().AsString();
        }
    }

OK 配置搞定。

直接测试下看看。

var configure = new Configuration();
            configure.SessionFactoryName("Demo");
            configure.DataBaseIntegration(db =>
            {
                db.Dialect<MsSql2005Dialect>();
                db.Driver<SqlClientDriver>();
                db.ConnectionString = @"Data Source=*;Initial Catalog=Database;User ID=sa;Password=123456;";
                db.LogSqlInConsole = true;
            });
            configure.AddMapping(new DatabaseMapper().CompileMappingForAllExplicitlyAddedEntities());

            SchemaMetadataUpdater.QuoteTableAndColumns(configure);
            new SchemaExport(configure).Create(false, true);

            using (ISession session = configure.BuildSessionFactory().OpenSession())
            {
                var company = new Company()
                {
                    CompanyName = "TestCompany",
                    CompanyDescription = "Description",
                    CreateTime = DateTime.Now
                };

                for (int i = 0; i < 100; i++)
                {
                    var group = new CompanyGroup(Guid.NewGuid().ToString());
                    group.CreateTime = DateTime.Now;
                    group.CompanyGroupName = "Test" + i.ToString();
                    company.AddCompanyGroup(group);
                }

                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Save(company);
                    transaction.Commit();
                }
            }

            using (ISession session = configure.BuildSessionFactory().OpenSession())
            {
                var info = session.Get<Company>(1L);
            }

            using (ISession session = configure.BuildSessionFactory().OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    var info = session.Get<Company>(1L);
                    session.Delete(info);
                    transaction.Commit();
                }
            }

            using (ISession session = configure.BuildSessionFactory().OpenSession())
            {
                var pagesize = 10;
                var current = 1;

                var count = session.QueryOver<CompanyGroup>().Where(r => r.Company.CompanyId == 1).RowCount();
                var infos = session.QueryOver<CompanyGroup>().Where(r => r.Company.CompanyId == 1).Skip(current * pagesize - pagesize).Take(pagesize).List();
                Console.WriteLine(count);
            }

很简单实现了增删改查,级联操作,和多关系操作。

感谢李永京的NHibernate讲解,俺也是看着他的博客入门的,在他的博客里讲解的很详细,有兴趣的可以去看下。

一点一滴之NHibernate的更多相关文章

  1. Nhibernate的Session管理

    参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...

  2. "NHibernate.Exceptions.GenericADOException: could not load an entity" 解决方案

     今天,测试一个项目的时候,抛出了这个莫名其妙的异常,然后就开始了一天的调试之旅... 花了很长时间,没有从代码找出任何问题... 那么到底哪里出问题呢? 根据下面那段长长的错误日志: -- ::, ...

  3. nhibernate连接11g数据库

    我框架的数据映射用 nhibernate连接多数据库,这次又增加了oracle11g,负责开发的同事始终连接不上,悲催的sharepoint调试是在不方便... 下面描述下问题的解决,细节问题有3个: ...

  4. 全自动迁移数据库的实现 (Fluent NHibernate, Entity Framework Core)

    在开发涉及到数据库的程序时,常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况,这时就需要进行数据库迁移. 实现数据库迁移有很多种办法,从手动管理各个版本的ddl脚本,到实现自己的mig ...

  5. 跟我学习NHibernate (1)

    引言:Nibernate概述 NHibernate是一个ORM框架,NHibernate是一个把C#对象世界和关系世界数据库之间联系起来的一座桥梁.NHibernate 能自动映射实体模型到数据库,所 ...

  6. 让OData和NHibernate结合进行动态查询

    OData是一个非常灵活的RESTful API,如果要做出强大的查询API,那么OData就强烈推荐了.http://www.odata.org/ OData的特点就是可以根据传入参数动态生成Ent ...

  7. MVC Nhibernate 示例

    首先,非常感谢提出问题的朋友们,使得本人又去深入研究了NHibernate的<Session-Per-Request 模式>.   前言: 谈到NHibernate大伙并不陌生,搞Java ...

  8. Nhibernate mapping 文件编写

    生成工具软件 现在生成工具软件有很多了,例如商业软件:NMG.CodeSmith.Visual NHibernate,开源软件:MyGeneration.NHibernate Modeller.AjG ...

  9. NHibernate之映射文件配置说明

    NHibernate之映射文件配置说明 1. hibernate-mapping 这个元素包括以下可选的属性.schema属性,指明了这个映射所引用的表所在的schema名称.假若指定了这个属性, 表 ...

随机推荐

  1. ubuntu14.04中文楷体变默认字体

    使用ubuntu以来,最让人头疼的事情就是在英文系统里面使用中文,一般中文字体都很难看,要么有锯齿,要么就是楷体.经过网上搜索找到一堆方法.一个个尝试之后觉得以下方式是最简单有效的. 1.安装font ...

  2. linux下ssh远程登录服务器入门操作

    使用用户名密码登录 在命令行中输入命令: ssh username@ip_address -p port 之后系统会提示输入密码,输入后即可登录 如果不添加-p选项,则默认是22端口 还可以使用-l选 ...

  3. atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php

    atitit.  集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby  与 事 ...

  4. atitit. java queue 队列体系and自定义基于数据库的队列总结o7t

    atitit. java queue 队列体系and自定义基于数据库的队列总结o7t 1. 阻塞队列和非阻塞队列 1 2. java.util.Queue接口, 1 3. ConcurrentLink ...

  5. Activemq 平台搭建与C#示列

    ActiveMQ ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS ...

  6. 在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。

    //在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’:输出这个数组中的所有元素. char [][]y=new char [10][10 ...

  7. [苏飞开发助手V1.0测试版]官方教程与升级报告

           [苏飞开发助手V1.0测试版]官方教程与升级报告导读部分----------------------------------------------------------------- ...

  8. Git – fatal: Unable to create ‘/.git/index.lock’: File exists错误解决办法

    有时候在提交的时候,中间提交出错,导致有文件被lock,所以会报下面的错误: fatal: Unable to create ‘/msg/.git/index.lock’: File exists. ...

  9. js遍历jsonTree

    var json = [{tcName:"11", children:[{tcName:"22", children:[{tcName:"33&quo ...

  10. ubuntu 16.04 samba 文件共享

    生成samba用户名密码修改配置文件重启samba服务使之生效 以前在ubuntu 14.04的时候,很方便的通过几行命令和一个GUI界面就可以配置好samba共享文件给windows了: Ubunt ...