[原创]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

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

点击下载源代码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员的SOD蜜

DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架

引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 《领域驱动设计系列(一):为何要领域驱动设计? 》文章中有下面一段话,对DDD使用产生的疑问: •没...

39290
来自专栏跟着阿笨一起玩NET

C# 中参数验证方式的演变

一般在写方法的时候,第一步就是进行参数验证,这也体现了编码者的细心和缜密,但是在很多时候这个过程很枯燥和乏味,比如在拿到一个API设计文档的时候,通常会规定类型...

15620
来自专栏hbbliyong

依赖注入(IOC)二

上一章我们讲了构造注入与设值注入,这一篇我们主要讲接口注入与特性注入。 接口注入 接口注入是将抽象类型的入口以方法定义在一个接口中,如果客户类型需要获得这个...

36170
来自专栏NetCore

一个让人遗忘的角落—Exception(二)

在上一篇中"一个被人遗忘的角落--Exception(一)"中,跟大家简单介绍了一下Exception,也使大家充分的了解了Exception管理在一个项目中的...

20290
来自专栏Android知识点总结

3-AIV--使用ContentProvider获得所有图片路径

20620
来自专栏JackieZheng

开发人员看测试之细说JBehave

上篇我们说到如何从Github上clone出一个JBehave项目,既是为了学习JBehava,也是为了熟悉下Github。 从clone下来的项目看来,基本没...

308100
来自专栏更流畅、简洁的软件开发方式

我的数据访问类(第二版)—— for .net2.0 (一)

asp.net2.0已经出来好久了,由于许多的原因一直没有使用,一个月前才开始使用VS2005写东西。 这一个月里又重新学习了一下基础知识,比如多态、接口了什么...

21790
来自专栏MelonTeam专栏

What's New in LLVM 9

导语 :这绝不仅仅是一篇 WWDC 2017 Session 411 学习笔记。除了有关 LLVM 9.0 的新特性之外,还有关于静态分析器和 Clang 5 ...

346100
来自专栏MasiMaro 的技术博文

ATL模板库中的OLEDB与ADO

上次将OLEDB的所有内容基本上都说完了,从之前的示例上来看OLEDB中有许多变量的定义,什么结果集对象、session对象、命令对象,还有各种缓冲等等,总体上...

15920
来自专栏XAI

微信企业号登录授权Java实现获取员工userid根据userid换openid

微信企业号登录授权Java实现获取员工userid根据userid换openid 2016年1月8日 为了方便测试 。debug 建议大家搞个花生壳或者其他的可...

1.2K90

扫码关注云+社区

领取腾讯云代金券