一对多映射.NHibernate

本文关键字:NHibernate 映射 一对多 | 更新日期: 2023-09-27 18:10:10

我正在看《NHibernate 3初学者指南》这本书,发现了一个有趣的提示:

在实际的库存应用程序中,您可能希望避免将Products集合放到Category实体上一个类别可能有数百个,如果不是数千个的话相关的产品。加载整个庞大的产品集合对于一个给定的类别是不明智的,并且会导致申请响应时间不理想。

Tip紧随一对多关系建立的例子之后。实体分别为ProductCategory。这个例子非常简单:

public class Category : Entity // Entity probably contains an `Id` property
{
    private List<Products> products;
    public String CategoryName { get; set; }
    public String Description  { get; set; }
    public IEnumerable<Product> Products { get { return products; } }
}  
public class Product : Entity
{
    public Decimal UnitPrice { get; set; }
    public String ProductName { get; set; }
    public Category Category { get; set; }
}

那么一对多关系的现实例子是什么呢?

仅仅将Category作为String属性放入产品实体中就足够了吗?

一对多映射.NHibernate

这个想法是,如果您完全避免使用IList属性,您仍然可以获得一个类别的产品,例如如下:

var products = session.QueryOver<Product>().Where(p => p.Category == someCategory).List();

但你现在有可能做分页,过滤,获得顶级产品等:

var product = session.QueryOver<Product>().Where(p => p.Category == someCategory).OrderBy(p => p.Relevance).Take(1).SingleOrDefault();

,如果它是一个简单的IList属性,则没有。一般来说(以我的经验),双向关联越少,查询粒度就越好。此外,它还减少了您在保存时的复杂性。

您可能想看看Nhibernate的lazy属性。它允许你不加载该属性,除非我们明确要求它。

Nhibernate懒惰

让我们问不同的问题:如果您的应用程序应该在树视图控件中显示类别,在展开类别节点时将列出所有产品,该怎么办?当你想展示所有的产品时,除了……实际查询数据库并加载所有产品

这实际上是非常常见的现实生活场景,最简单的方法之一确实是简单地使用Category.Products属性。当然,拥有这样的属性并没有错,但真正的问题是您应该如何管理这些对象。

幸运的是,你不需要用单一类别拉所有的产品。可以将Category.Products标记为惰性加载(与急切加载相反,可以在这里找到更多信息)。这意味着,加载类别不会查询其产品的数据库。相反,NHibernate将为Products创建代理对象,可以稍后初始化-当它们实际需要时(想想用户扩展类别节点)。


我来回答你的问题…

如果单个产品绑定到恰好一个类别,那么它就是一个很好的现实生活中的一对多关系示例。但是,如果产品可以用一个以上的类别来描述,那么它就是多对多关系。

我认为引号会说你根本不应该在Category类中使用Products属性