Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate difference between Query<T>, Get<T> and Load<T>

I'd like to find the difference in using these three ways of getting data from the database when doing something like:

public T GetById(int id) {
    using (var db = Database.Session) {
        using (var t = db.BeginTransaction()) {
            try {
                return db.Get<T>(id);
            }
            catch (Exception) {
                if (!t.WasCommitted) {
                    t.Rollback();
                }
                throw;
            }
        }
    }
}

or

public T GetById(int id) {
    using (var db = Database.Session) {
        using (var t = db.BeginTransaction()) {
            try {
                return Query<T>().First(x=>x.Id == id);
                //or something like
                //return Query<T>().Where(x=>x.Id == id).FirstOrDefault();
                //or
                //return QueryOver<T>().Where(x=>x.Id == id).FirstOrDefault;
            }
            catch (Exception) {
                if (!t.WasCommitted) {
                    t.Rollback();
                }
                throw;
            }
        }
    }
}

or even this way:

public T GetById(int id) {
    using (var db = Database.Session) {
        using (var t = db.BeginTransaction()) {
            try {
                return db.Load<T>(id);
            }
            catch (Exception) {
                if (!t.WasCommitted) {
                    t.Rollback();
                }
                throw;
            }
        }
    }
}

And adding another question to this one, how the Query() differs from QueryOver()?

I've read some answers here in stackoverflow but since the majority of them was about the starting of using Linq, and NHibernate 3, I'd like to know how is the scenario today.

like image 897
Diego Barreto Avatar asked Sep 18 '25 09:09

Diego Barreto


2 Answers

Similar try to explain it is here

In general we've got three ways how to get an instance from DB by its ID.

1) Querying - That is where we use QueryOver API (native NHibernate language) or Query (implementation of the MS LINQ API). These queries always hit the DB (or cache) and could load full root object, fetch some relations, or be just projections (only few columns/properties converted into some DTO)

2) Then, we have Get<TEntity>(), which was intended as the most common way how to get item by ID. It always hits DB because its contract says (get):

Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance

So, to be sure that object exists or not, DB must be hit.

3) Finally, there is a third contract - Load<TEntity>(). It will never hit DB to check if there is such an item (with provided ID): load():

Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.

If we've got a reference ID, and we know that it does exist we should use the Load<TEntity>().

It will just create a proxy - with provided ID and during the INSERT or UPDATE of that root/holder entity, the proxy ID will be used to create correct SQL Statement.

Summary: Get() and Load() are there for us for a reason. They were designed to support different scenarios.

See also:

  • Different between session.get() and session.load()
  • NHibernate – The difference between Get, Load and querying by id
like image 108
Radim Köhler Avatar answered Sep 19 '25 22:09

Radim Köhler


how the Query() differs from QueryOver()?

QueryOver is a strongly-typed version of Criteria, and is more NHibernate specific. Pretty much anything you can do in ICriteria can be done with QueryOver. In the golden days of ICriteria NH2 you always had to cast, hence this is why now you need to cast at the end of the chain back to an int.

LINQ (Query) is a standard query method that works on IQueryable that doesn't need explicit references to NHibernate and can be considered more ORM agnostic and therefore follows the linq standard. As you rightly pointed out you do not need to cast to an int as your are selecting into the result the customNumber.

like image 30
Nazmul Hasan Avatar answered Sep 19 '25 23:09

Nazmul Hasan