简体   繁体   中英

One to many mapping. NHibernate

I was looking at 'NHibernate 3 Beginner's Guide' book and found interesting tip:

In a real life inventory application, you will probably want to avoid putting a Products collection on the Category entity, as it is possible that a category can have hundreds, if not thousands, of associated products. To load the whole, huge collection of products for a given category would be unwise and would lead to an application having unsatisfactory response times.

Tip was right after an example of one-to-many relationships building. The entities were Product and Category . The example is quite straightforward:

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; }
}

So what is the real life example of one-to-many relationships?

Would it be enough for the example just to put Category inside a product entity as a String property?

You may want to have a look a the lazy property of Nhibernate.It allows you not to load that property always unless we explicitly asks for it.

Nhibernate Lazy

The idea is that if you avoid the IList property all-together, you can still get to the products for a category eg like the following:

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

But you now have the possibility to do paging, filtering, getting the top product etc.:

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

which you do not have if it is a simple IList property. In general (in my experience), the less two-way ascociations you have, the better your querying granularity will be. Also, it reduces your complexity when it comes to saving.

Let's ask different question: what if your application should present categories in tree-view control, which upon expanding category node will list all products? When you want to display all products there's no other way than ... actually querying database and loading all products.

That's actually pretty common real-life scenario and one of easiest approaches is indeed to simply have Category.Products property. Of course there's nothing wrong with having such property, but the real question is how you should manage those objects.

Luckily, you don't have to pull all the products with single category pull. Category.Products can be marked to load lazily (as opposed to eagerly , more information can be found here ). What this means is, loading category won't query database for its products. Instead, NHibernate will create proxy object for Products , which can be initialized later - when they are actually needed (think user expanding category node).


And to answer your question...

If single product is bound to exactly one category, then it's good real-life one-to-many relation example. However, if product can be described by more than one category, it's many-to-many relation then.

我认为引号将表明您根本不应使用Category类中的Products属性。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM