Posts

Showing posts with the label NHibernate

Ways to perform eager loading via NHibernate

By default we know that lazy loading is enabled in NHibernate. So, let's say if we decide to keep the default, how do we enable eager loading with NHibernate? There are 2 ways to do that (there are more, but I will mention 2 that you will commonly see): 1.  Query<Entity>().Fetch(x => x.ClassA).Fetch(x => x.ClassB); 2. var tempQuery =  Query<Entity>().Fetch(x => x.ClassA).ToFuture();      Query<Entity>(). Fetch(x => x.ClassB).ToFuture();     var entityList =  tempQuery   .ToList(); Do note that Fetch is used to fetch reference, while FetchMany is used to fetch collection. If you are wondering what is the difference between 1 and 2, it is the use of ToFuture to split the SQL statement to multiple queries. The problem with multiple Fetch in a single LINQ query is that it would result in Cartesian product of the main object, in this case, Entity  . Hence, it is not recommended to use multiple...

Generic query with NHibernate with eager loading

In my previous post, I showed how we could create generic methods to perform query,  https://csharptipstricks.blogspot.com/2019/12/usage-of-expression-to-create-generic.html . However, the methods present there does not allow eager loading. In case you are wondering how eager loading is performed, see below. Do know that there are ways to assign eager loading during mapping, but I will not show it in this post. Method I : SessionFactory.OpenSession().Query<MyEntity>().Fetch(x => x.Property1).Fetch(x => x.Property2).ToList(); Method II : var tempMyEntityQuery = GetSession().Query<MyEntity>().Fetch(x => x.Property1).ToFuture(); GetSession().Query<MyEntity>().Fetch(x => x.Property2).ToFuture(); List<MyEntity> myEntityList = tempMyEntityQuery .ToList(); Both the methods above will eager load Property1 & Property2 in a single trip to the database. However, I would choose method I because a single statement (with left outer join)...

The danger of duplicated mapping of many-to-one in NHibernate

If you use NHibernate, you will often have to deal with lots of many-to-one mapping. However, if you are not careful, you might accidentally create duplicated mapping due to the use of foreign key. Let's say you have a class,  A ,   which has a column, A_ID as the primary key. Class  B is related to A via a column, A_ID (in B), which is the foreign key referencing A 's primary key. Hence, we would define our B object like the following, public class B { public virtual A ClassA { get ; set ; } public virtual long A_ID { get ; set ; } } We have both the properties to represent the object A (due to the foreign key mapping), as well as the column which acts as the foreign key. The following is the XML mapping file. <property name="A_ID">       <column name="A_ID" not-null="true" /> </property> <many-to-one name="ClassA" column="A_ID" cascade="save-update"/> We want ...

Usage of Expression to create generic query method for NHibernate

In my previous post about caching and generic query via NHibernate [ https://csharptipstricks.blogspot.com/2019/12/caching-and-generic-query-using.html ], there was a method that takes Expression as a parameter, as shown below: // Check if a record exists or not public async Task< bool > IsRecordExistsAsync<K>(Expression<Func<K, bool >> condition) where K : class { bool isExist = await GetSession().QueryOver<K>() .Where(condition) .RowCountAsync() > 0; return isExist; } Initially, I had the intention of creating a common method which could produce an Expression that holds a Func<K, bool> delegate. The method is as follow: public static Expression<Func<T, bool >> CreateCondition<T>(Func<T, bool > func) { return x => func(x); } When I use the Expression produced via the method above as an input parameter fo...

Caching and generic query using NHibernate [.NET Core]

One of the important aspects in API design is to reduce the number of fetch request to database. NHibernate provides 2 levels of caching, with the first level cache persist through a session only, while the 2nd level cache persists across multiple sessions. The second level cache can be implemented by installing the NuGet package of NHibernate.Caches.SysCache . Then, it involves some configuration setup to utilize the cache feature. However, there is an alternative way that exists in .NET Core which we could use to build a simpler cache. The caching that we could use is IMemoryCache . Firstly, we could setup the cache during  ConfigureServices . public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); } Then, assuming we want to retrieve all the records from a table called DailySales , and we want to keep the records in the cache for 1 minute, we could do the following. private readonly IMemoryCache cache; public DBHelper(IMe...