Skip to main content

NHibernate–Lazy loading without a proxy

Yes, it is 2023 and yes I'm still using NHibernate at some of my projects(sorry old habits die hard).

One of the things that is really handy but can bite you in the foot as easily, is lazy loading.

What is lazy loading?

Lazy loading is used to delay the retrieval of related data from a database until it is actually accessed or requested by the application. ORM frameworks, like NHibernate or Entity Framework, map database tables to objects in your programming language, making it easier to work with relational data in an object-oriented manner.

When an ORM employs lazy loading for related data, it means that the ORM does not fetch all the associated data immediately when you query for the main entity. Instead, it loads the related data from the database only when you explicitly access or request that data. This approach helps improve performance by reducing the initial amount of data fetched from the database and minimizing the number of database queries.

Here's an example to illustrate how lazy loading works in the context of ORM:

Let's say you have two entities, Author and Book, with a one-to-many relationship (an author can have multiple books). With lazy loading enabled, if you retrieve an Author object from the database, the ORM might only fetch the author's information and not load the associated books immediately. Only when you access the books property of the Author object will the ORM issue an additional query to fetch the books associated with that author.

Benefits of lazy loading in ORM:

  1. Reduced Data Transfer: Lazy loading minimizes the amount of data transferred from the database to the application initially, which can lead to faster query execution and lower network traffic.

  2. Efficient Resource Usage: Since related data is loaded only when needed, resources like memory and network connections are used more efficiently.

  3. Improved Performance: Loading related data on-demand can lead to faster initial query execution times, which is especially beneficial in scenarios where not all related data is required for every operation.

However, lazy loading can also introduce some challenges:

  1. N+1 Query Problem: If lazy loading is used excessively and not managed properly, it can lead to the "N+1 query problem," where fetching a collection of entities results in N additional queries to load their related data. This can cause performance issues.

  2. Unintentional Overhead: Developers need to be mindful of when and how they access related data to avoid triggering unnecessary database queries and performance bottlenecks.

  3. Complexity: Managing lazy loading and ensuring that related data is loaded appropriately can add complexity to the application code.

To address these challenges, many ORM frameworks provide options for customizing lazy loading behavior, like specifying eager loading (loading related data along with the main entity) or utilizing batch loading techniques to minimize the number of queries. Developers should carefully consider the trade-offs between eager and lazy loading based on their specific application's requirements and performance considerations.

How lazy loading works in NHibernate

In NHibernate lazy loading is enabled by default. To make this work NHibernate uses out-of-the-box a proxy object. This proxy objects sits in between your object and an associated relation(for example between the Author and its Books).

Remark: To make this work NHibernate requires that all properties and methods in your object are declared as virtual if lazy loading is enabled.

Here is an example in NHibernate:

Lazy loading without a proxy

Although the usage of proxies is the default way in NHibernate it is a leaky abstraction and can result to unexpected behavior. For example as explained in this post, the following code will not work as expected:

We are checking the type of what is returned but this is not the object itself but instead a proxy instance.

To avoid this issue, you can change the lazy loading behavior in NHibernate to not using a proxy but fetch the actual object the first time you access the property.

This is how to do it using the conformist mapping:

Or using Fluent NHibernate:

Popular posts from this blog

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Cleaner switch expressions with pattern matching in C#

Ever find yourself mapping multiple string values to the same result? Being a C# developer for a long time, I sometimes forget that the C# has evolved so I still dare to chain case labels or reach for a dictionary. Of course with pattern matching this is no longer necessary. With pattern matching, you can express things inline, declaratively, and with zero repetition. A small example I was working on a small script that should invoke different actions depending on the environment. As our developers were using different variations for the same environment e.g.  "tst" alongside "test" , "prd" alongside "prod" .  We asked to streamline this a long time ago, but as these things happen, we still see variations in the wild. This brought me to the following code that is a perfect example for pattern matching: The or keyword here is a logical pattern combinator , not a boolean operator. It matches if either of the specified pattern...