[原创]Fluent NHibernate之旅(四)-- 关系(中)

接着上一篇,我们继续讲解ORM中的关系。在数据库设计中,我们最多打交道的,要算一对多关系了,延续我们的示例,我们来讲解一下一对多的关系。

Fluent NHibernate之旅系列导航:

一、开篇:ISessionFactory Configuration

二、实体映射:Entity Mapping

三、继承映射:Inheritence Mapping

四、一对一映射:One-to-One Mapping

场景和数据库设计

延续我们的演示范例,用户和订单是非常典型的一对多范例。

1、一个用户可以拥有多个订单

2、一个订单只能拥有一个用户

对于用户来说,不需要每次都加载订单列表,反之订单可能每次都需要加载用户信息。Let's Go:

我们原先的订单系统太贫血了,我们进一步扩展一下,现在已经可以储存收货人的姓名和地址,还包括了发起人的UserID。

映射

不得不赞叹一下 Fluent Nhibernate ,有了它,我们的映射一切都变得如此简单,先来看看Model吧,用户的订单列表,对于用户来说,暂时是不需要排序的,所以我们可以使用ISet作为Order的列表。

public class User
{
    public virtual int UserID { get; set; }

    public virtual string UserName { get; set; }

    public virtual string Password { get; set; }

    public virtual DateTime CreateTime { get; set; }

    public virtual UserDetail Detail { get; set; }

    public ISet<Order> Orders { get; set; }
}

public class Order
{
    public virtual int OrderID { get; set; }

    public virtual float Price { get; set; }

    public virtual OrderState State { get; set; }

    public virtual DateTime CreateTime { get; set; }

    public virtual User User { get; set; }

    public virtual string Address { get; set; }

    public virtual string Zip { get; set; }

    public virtual string Coignee { get; set; }
}

好,我们看看Fluent如何映射吧,你会发觉,一切就是这么简单:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(u => u.UserID).GeneratedBy.Identity() ;
        Map(u => u.UserName);
        Map(u => u.Password);
        Map(u => u.CreateTime);
        HasOne<UserDetail>(u => u.Detail).Cascade.All().Fetch.Select();
        HasMany<Order>(u => u.Orders).AsSet().KeyColumn("UserID").Cascade.All();
    }
}

public class OrderMap : ClassMap<Order>
{
    public OrderMap()
    {
        Id(o => o.OrderID).GeneratedBy.Identity();
        Map(o => o.Price);
        Map(o => o.State).CustomType<OrderState>();
        Map(o => o.Address);
        Map(o => o.Coignee);
        Map(o => o.CreateTime);
        Map(o => o.Zip);
        References<User>(o => o.User).Not.LazyLoad().Column("UserID");
    }
}

怎么样,简单明了吧,比传统方式要容易懂吧,看一下我们的测试结果:

[Fact]
public void CreateOrder()
{
    var factory = FluentSessionFactory.GetCurrentFactory();
    using (var session = factory.OpenSession())
    {
        User user = session.Get<User>(1);
        Order order = new Order()
        {
            Address = "James & Candy 's Home",
            Coignee = "Candy",
            CreateTime = DateTime.Now,
            Price = 1500,
            State = OrderState.Created,
            Zip = "200000",
        };

        order.User = user;
        session.Save(order);
    }
}

 

一对多的映射,比起一对一来说还相对的简单点,默认是延迟加载,如果项目中,有些地方,需要立即加载,我们也可以使用 FetchMode.Eager 来加载。

立即加载

[Fact]
public void Test_User_Eager_Orders()
{
    var factory = FluentSessionFactory.GetCurrentFactory();
    User user;
    using (var session = factory.OpenSession())
    {
        user = session.CreateCriteria<User>()
                            .SetFetchMode("Orders", FetchMode.Eager)
                            .List<User>().FirstOrDefault();
    }

    Assert.NotNull(user);
    Assert.Equal(true, user.Orders.Any());
}

这里为什么没有在using中进行测试,就是为了表示,我们立即加载了Orders属性,来看看我们的测试结果:

我们在Output中,能看到NHibernate生成的Sql语句,测试也成功,说明我们刚刚是立即加载了Orders属性。

总结

总体来说,一对多的映射比较简单点,不过我们今天只是说了一般的情况,但如果我们遇到级联更新、级联删除等,就会遇到一些问题,在后续文章中会慢慢道来。

如果您在使用Fluent Nhibernate的时候也遇到了问题,可以及时与我联系或求助于Fluent 的Google Groups

应“亦续缘”的要求,我把代码整理了下,发上来,便于大家学习。

点击下载源代码

时间: 2024-09-10 15:07:25

[原创]Fluent NHibernate之旅(四)-- 关系(中)的相关文章

[原创]Fluent NHibernate之旅(四)-- 关系(上)

经过了前面三篇的介绍,相信大家对Fluent NHibernate已经有一定的了解了,在我们学习中,Fluent 也已经进入了RTM版本.这次的版本发布离RC版只有半个月不到,修正了很多bug,同时补充了大量的功能,在每天更新中,也看到了大量的单元测试,我们相信Fluent NHibernate 已经相对稳定成熟了.RTM相对于RC版本来说,使用方法没有太大的变化,所以不做讲解. 我们后面的教程,会使用RTM版本来演示,希望大家能及时更新(点击下载最新版). Fluent NHibernate之

[原创]Fluent NHibernate之旅二--Entity Mapping

接着上一篇,今天我们说说ORM中的Mapping.如果你要体验NHibernate的强大,首先你就要学会配置,包括SessionFactory和Mapping的配置.今天跟上一篇一样,会使用传统方式和 NHibernate 进行讲解.如果你要亲手试验一下,可以先看一下"Fluent NHibernate之旅一",进行一下数据库和SessionFactory的准备. 本节内容: 简单实体映射 使用自定义类型映射实体属性 NHibernate的实体映射(Entity Mapping)做的非

[原创]Fluent NHibernate之旅(四)-- 关系(下)

最近一直忙着准备去旅行的东东,所以进度慢下来了,明天就要出发了,嘿嘿,在出发前,把多对多给写完吧.如果你第一次看这个系列,可以先看看先前几篇,了解下. 一.开篇:ISessionFactory Configuration 二.实体映射:Entity Mapping 三.继承映射:Inheritence Mapping 四.一对一映射:One-to-One Mapping 五.一对多映射:One-to-Many Mapping 场景和数据库设计 前两篇我们介绍了"一对一"和"一

[原创]Fluent NHibernate之旅

ORM大家都非常熟悉了吧,我相信也有很多朋友正在用自己或者一些公开的框架,而最常用而且强大的,非Hibernate了(Net中为NHibernate),网上的文档非常多,不过在博客园中,介绍NHibernate的非常少,李哥的NHibernate系列(NHibernate之旅)不失为一个经典,对于新手的我们,需要完全掌握还需要很长一段路,对于新手来说,最初的配置是非常头大的一件事情,好在老赵推荐一个开源的框架Fluent NHibernate,有了它,我们可以完全脱离配置文件,不过博客园中介绍F

[原创]Fluent NHibernate之旅(三)-- 继承

经过了"开篇"和"简单映射"两篇文章,相信大家对Fluent NHibernate 有了一定的了解了,FluentNHibernate实际就是对 NHibernate 映射的一定扩展,我们能完全利用强类型.泛型.Lambde表达式等等Vs.Framework等特性简单完成映射工作,同时也能让我们学习NHibernate的映射方式,一举夺得,这么好玩的东东,有理由不继续完成这个系列吗?废话不说,回到正题. 从这一篇开始,我们将使用Fluent NHibernate R

Fluent NHibernate 之旅 导航篇

ORM大家都非常熟悉了吧,我相信也有很多朋友正在用自己或者一些公开的框架,而最常用而且强大的,非Hibernate了(Net中为NHibernate),网上的文档非常多,不过在博客园中,介绍NHibernate的非常少,李哥的NHibernate系列(NHibernate之旅)不失为一个经典,对于新手的我们,需要完全掌握还需要很长一段路,对于新手来说,最初的配置是非常头大的一件事情,好在老赵推荐一个开源的框架Fluent NHibernate,有了它,我们可以完全脱离配置文件,不过博客园中介绍F

Fluent Nhibernate之旅(五)--利用AutoMapping进行简单开发

Fluent Nhibernate(以下简称FN)发展到如今,已经相当成熟了,在Nhibernate的书中也相应的推荐了使用FN来进行映射配置,之前写的FN之旅至今还有很多人会来私信我问题,说来惭愧,从FN之旅四至今已经4年多,至今还未更新过此系列,原因有很多,最大的就是懒惰,哈. 安装 现在在项目中使用FN很方便,使用Nuget管理就可以了,但我还是建议大家,可以下载源代码,自己可以详细了解下. 当然,您也可以用命令台来进行安装.说个题外话,NuGet真心不错,至少已经做新项目的时候不用到处去

[Fluent NHibernate]一对多关系处理

目录 写在前面 系列文章 一对多关系 总结 写在前面 上篇文章简单介绍了,Fluent Nhibernate使用代码的方式生成Nhibernate的配置文件,以及如何生成持久化类的映射文件.通过上篇的学习你会发现,Fluent Nhibernate仍然需要引用Nhibernate的两个程序集(Nhibernate.dll和Iesi.Collections.dll),所以与Nhibernate最大的区别就在生成配置文件的方式上面,这里关于Nhibernate的特性方面就不再多赘述,可以参考Nhib

如何使用Fluent Nhibernate中的Automapping进行OR Mapping映射

由于在项目中使用了NHibernate来作为ORMapping构建数据访问层,那么就必须要配置Object和DataTable的映射.最早的项目中,我们使用了最传统的XML配置文件的方式编写映射关系,但是这样太麻烦,每次修改class和表时都要去修改对应的XML文件,而且还容易出错,一定有疏忽遗漏的地方,还不容易找出错误,所以在第二个项目中,我们使用了Fluent NHibernate的Mapping方式代替XML配置.使用Fluent NHibernate的最大好处是降低了出错的机会,因为Fl