之前介绍了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. 点击div外面该div消失(二)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. JQuery官方学习资料(译):使用JQuery的.index()方法

        .index()是一个JQuery对象方法,一般用于搜索JQuery对象上一个给定的元素.该方法有四种不同的函数签名,接下来将讲解这四种函数签名的具体用法. 无参数的.index() < ...

  3. JDK版本不兼容问题之:一台机器安装多个版本的JDK

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://guojie.blog.51cto.com/59049/45964 我的机器上最开 ...

  4. Android 实用工具Hierarchy Viewer实战

    在Android的SDK工具包中,有很多十分有用的工具,可以帮助程序员开发和测试Android应用程序,大大提高其工作效率.其中的一款叫Hierachy Viewer的可视化调试工具,可以很方便地在开 ...

  5. CStringArray用法

    CStringArray使用之前先设置数组尺寸SetSize,才能使用SetAt                  CStringArray m_strScrkRfid ;               ...

  6. 强烈推荐android studio用的几个插件

    http://blog.csdn.net/liang5630/article/details/46366901 android studio常用插件,可极大简化开发,增强开发效率. 不懂安装studi ...

  7. c#之第二课

    输出语句: /////////////////////////////// public class Hello1 { public static void Main() { System.Conso ...

  8. 谈一谈PHP的代码重构

    随着 PHP 从一种简单的脚本语言转变为一种成熟的编程语言,一个典型的 PHP 应用程序的代码库的复杂性也随之增大.为了控制对这些应用程序的支持和维护,我们可以使用各种测试工具来自动化该流程.其中一种 ...

  9. Swift - UIView的无损截图

    Swift - UIView的无损截图 效果 源码 // // UIView+ScreensShot.swift // Swift-Animations // // Created by YouXia ...

  10. Maven 简单配置gpg

    1. 下载maven到指定目录,指定对应的gpg的执行命令所需要的属性.这里比如下载解压后的maven目录是: C:\maven-apache-3.3.2 ,那么配置文件目录是: C:\maven-a ...