Spiga

NHibernate2.1新特性之EntityMode.Map

2009-08-05 08:47 by 李永京, 3631 visits, 收藏, 编辑

NHibernate2.1新特性之EntityMode.Map

本节内容

  • 引入
  • EntityMode
  • 典型实例
    • 1.映射文件
    • 2.Configuration配置
    • 3.测试
  • 结语

引入

假设你想要持久化设计模型,而你不想写任何Domain实体。

假设你想在原有数据基础上测试ORM错误;而你不想写任何实体界面也没有任何实体实现。

假设朋友之间互相讨论问题,传你一些NH映射文件,来优化数据访问,但他并没有传你他的具体实现。

.........

总之,你就一堆NHibernate Mapping文件,你怎么办呢?按照映射结构试着重现Domain?还是直接放弃这些Mapping文件了?

不过我们有另外一个工具AjGenesis ,其IDE是AjGenesisStudio可以完成这项工作,但是学习成本的确高了点。

我可以告诉你,NHibernate可以做到,利用这些Mapping文件,对其测试,优化数据访问,如果你是世外高人甚至你的程序中没有Domain。

EntityMode

在NH2.1中EntityMode有三种,分别是:

  • POCO
  • Dynamic-Map (又称 Dictionary<PropertyName, PropertyValue>)
  • Xml

EntityMode.POCO在常见不过了,就是NHibernate默认实体模式,NHibernate按照POCO来映射实体,操作实体。事实上,我们对EntityMode.Map并不陌生,在原来映射dynamic-component中已经使用了这个功能,就是一个属性名称为键,属性值为值的字典。在NHibernate2.1中,EntityMode.Xml还未实现,就是可以映射XML文件。

EntityMode.Map也就是所谓的动态实体。

典型实例

自己构建的例子有点不“官方”,我还是从NHibernate源码中摘取一个典型的实例说明一下吧。就是一个Mapping文件,然后对Mapping文件进行测试,看这个文件是否正确!或者可以优化下映射,例如级联、二级缓存什么的。

1.映射文件

在映射文件中,要声明entity-name来代替一个类名,对于entity-name也是NHibernate2.1的一个新特性,以后再写这方面文章介绍一下。

看到这个映射文件应该很熟悉,两个Domain,双向父子关系,就是一个生产线有N个模型案例了。

<class entity-name="ProductLine">
    <id name="Id" type="int">
        <generator class="hilo"/>
    </id>
    <property name="Description" not-null="true" length="200" type="string"/>
    <bag name="Models" cascade="all" inverse="true">
        <key column="productId"/>
        <one-to-many class="Model"/>
    </bag>
</class>

<class entity-name="Model">
    <id name="Id" type="int">
        <generator class="hilo"/>
    </id>
    <property name="Name" not-null="true" length="25" type="string"/>
    <property name="Description" not-null="true" length="200" type="string"/>
    <many-to-one name="ProductLine" column="productId" not-null="true" class="ProductLine"/>
</class>

2.Configuration配置

NHibernate默认设置是POCO模式。我们可以配置default_entity_mode选项设置一个默认的实体模式,这里我在这个Configuration中把default_entity_mode设置为EntityMode.Map。

[TestFixtureSetUp]
public void TestFixtureSetUp()
{
    cfg = new Configuration();
    cfg.Configure();
    //默认EntityMode为Poco,这里把default_entity_mode设置为EntityMode.Map
    cfg.SetProperty("default_entity_mode", EntityModeHelper.ToString(EntityMode.Map));
    sf = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
}

3.测试

使用Dynamic-Map,就是一个字典,这里先new出来一个Hashtable的ProductLine,再new出来两个基于Hashtable的Model字典,对ProductLine保存级联保存Model。其中ISession.Save()方法也是最新增加的一重载方法,然后对其查询,最后删除测试。

[Test]
public void DynamicClasses()
{
    //一个生产线有N个模型,这里模拟汽车生产线
    IDictionary cars;
    IList models;
    using (ISession s = sf.OpenSession())
    {
        using (ITransaction t = s.BeginTransaction())
        {
            cars = new Hashtable();
            cars["Description"] = "Cars生产线";

            IDictionary ferrari = new Hashtable();
            ferrari["ProductLine"] = cars;
            ferrari["Name"] = "Dino";
            ferrari["Description"] = "法拉利Dino";

            IDictionary lamborghini = new Hashtable();
            lamborghini["ProductLine"] = cars;
            lamborghini["Name"] = "康塔克Countach";
            lamborghini["Description"] = "蓝博基尼_康塔克Countach";
            models = new List<IDictionary> { ferrari, lamborghini };

            cars["Models"] = models;
            //第一个参数为映射中使用的实体名称,第二个参数为实例
            s.Save("ProductLine", cars);
            t.Commit();
        }
    }

    using (ISession s = sf.OpenSession())
    {
        using (ITransaction t = s.BeginTransaction())
        {
            cars = (IDictionary)s
               .CreateQuery("from ProductLine pl order by pl.Description")
               .UniqueResult();
            models = (IList)cars["Models"];

            Assert.That(models.Count == 2);

            s.Clear();

            IList list = s.CreateQuery("from Model m").List();
            var model = (IDictionary)list[0];

            Assert.That(((IList)((IDictionary)model["ProductLine"])["Models"]).Contains(model));

            s.Clear();
            t.Commit();
        }
    }

    using (ISession s = sf.OpenSession())
    {
        using (ITransaction t = s.BeginTransaction())
        {
            cars = (IDictionary)s
              .CreateQuery("from ProductLine pl order by pl.Description")
              .UniqueResult();
            s.Delete(cars);
            t.Commit();
        }
    }
}

测试结果:

第一个Session:创建对象

EntityMode.Map测试

第二个Session:查询对象

EntityMode.Map测试

第三个Session:删除对象

EntityMode.Map测试

结语

当然了,我们可以利用EntityMode.Map的动态实体,把一堆没有Domain的Mapping文件进行测试,优化等操作。

我还是通过通俗易懂的语言一篇一篇来介绍NHibernate里面的秘密吧。大家对EntityMode.Map有什么好的应用,一起交流下咯。

NHibernate Q&A

希望本文对你有所帮助!

标签: NHibernate
Add your comment

16 条回复

  1. #1楼 kiler      2009-08-05 08:48
    占个沙发,lz学习速度好快啊。
     回复 引用 查看   
  2. #2楼[楼主] 李永京      2009-08-05 08:52
    @kiler
    学起来简单,写起来难.....把话说好,还是要考虑很多地方呢,不好写的那么呆板,要轻松活泼点。
     回复 引用 查看   
  3. #3楼 浅浅dě夕阳      2009-08-05 09:08
    @李永京
    学习了,李老师~呵呵。
    对了,我怎么加不了社区给出的QQ群啊?
     回复 引用 查看   
  4. #4楼[楼主] 李永京      2009-08-05 09:16
    @浅浅dě夕阳
    不清楚啊。可能满了
     回复 引用 查看   
  5. #5楼 沉默的糕点      2009-08-05 09:42
    谢谢分享。
     回复 引用 查看   
  6. #6楼 —无 名      2009-08-05 10:22
    谢谢LZ,学习了。
    不知道ibatis啥时候也出个ibatis linq
     回复 引用 查看   
  7. #7楼[楼主] 李永京      2009-08-05 10:30
    @—无 名
    iBATIS.NET一年多没更新了。
     回复 引用 查看   
  8. #8楼 yxiaoxiong      2009-08-05 13:07
    请教一下,测试结果的窗体是用什么来查看的?
     回复 引用 查看   
  9. #9楼[楼主] 李永京      2009-08-05 13:11
    引用yxiaoxiong:请教一下,测试结果的窗体是用什么来查看的?

    NHibernate Profiler工具,官方网站 http://nhprof.com/
     回复 引用 查看   
  10. #10楼 yxiaoxiong      2009-08-05 13:12
    @李永京
    引用李永京:
    引用yxiaoxiong:请教一下,测试结果的窗体是用什么来查看的?

    NHibernate Profiler工具,官方网站 http://nhprof.com/

    多谢!
     回复 引用 查看   
  11. #11楼 雄健      2009-08-20 08:45
    请问NHibernate Profiler工具是不是需要.net 3.0以上啊?
     回复 引用 查看   
  12. #12楼[楼主] 李永京      2009-08-20 09:02
    @雄健
    应该是.net3.5 他是VS2008设计的
     回复 引用 查看   
  13. #13楼 毁于随      2009-09-11 09:29
    真不错,NH越来越好了.顺便问一下博主,NH的文档是否也进行了更新呢?好像那种chm的,永远是1.X版本的.
     回复 引用 查看   
  14. #14楼[楼主] 李永京      2009-09-11 09:31
    @毁于随
    更新了,2.1版本的,sf上有下载的
     回复 引用 查看   
  15. #15楼 James.Ying      2009-10-21 13:13
    李老师,数据表怎么建立?建立一个ProductLine和Model表吗?如果不建立Domain实体,外部怎么去访问和使用呢?我很迷惑啊
     回复 引用 查看   
  16. #16楼[楼主] 李永京      2009-10-21 13:36
    @James.Ying
    数据库用NH自带工具生成的
    Map就是一个功能而已
     回复 引用 查看   
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1539215 UoTLj+iUu1c=