之前介绍了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. create mystic by Django

    See the sumary below figure : We going to talk each step ...more detail

  2. paip.互联网产品要成功的要素

    paip.互联网产品要成功的要素 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/atti ...

  3. paip. 混合编程的实现resin4 (自带Quercus ) 配置 php 环境

    paip. 混合编程的实现resin4 (自带Quercus ) 配置 php 环境 #---混合编程的类型 1.代码inline 方式 2.使用库/api  解析方式. #----配置resin 支 ...

  4. iOS开发-Alpha,Hidden与Opaque区别

    UIView中的这三个属性用的比较多,尤其是Alpha和Opaque之间有的时候不是很好分别,稍微整理下: Alpha(不透明度) alpha是不透明度,属性为浮点类型的值,取值范围从0到1.0,表示 ...

  5. Ubuntu 安装JDK步骤 ,提示没有那个文件或目录

    作为一个程序员,配置环境是最基本的功夫,然而我却捣鼓了一下午,包括安装Ubuntu,安装JDK和配置环境变量. 简单记录下自己的安装过程: 1  下载JDK tar包,使用tar -xzvf jdk* ...

  6. VC2010 调用 Webservice

    开发环境:VC2010,gsoap_2.8.23 http://blog.csdn.net/zhaiwenjuan/article/details/6590941 使用soapcpp2的时候要加参数- ...

  7. Cause for NullPointerException android.support.v7.widget.RecyclerView.onMeasure

    because you have not set LinearLayoutManager to RecyclerView. for example: mRecyclerView = (Recycler ...

  8. C#Winform程序如何发布并自动升级(图解)

    C#Winform程序如何发布并自动升级(图解)     有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布 关于打包的大家可以看我的文章C# w ...

  9. Dreamweaver8 查找和替换窗口不见了解决办法

    激活窗口,按下Atrl+空格,再按下M,方向键移动窗口,就回来了!

  10. 2014 Hangjs 见闻流水账第一天

    前言 6月21日~6月22日, 第一次跑远门去参加一个大会(广州 -> 杭州),本来打算,在火车的回来的路上,把这两天的东西记录一下,不过,火车上的环境实在恶劣,同时也高估了自己的专注力,所以, ...