How do I strongly type criteria when using NHibernate's CreateCriteria method? - nhibernate

I'm currently using NHibernate, for the first time, with Fluent NHibernate. I've gotten everything setup nicely, however now I've come to actual doing some data retrieval, it seems to have fallen short.
I was expecting NHibernate, to allow me to do something like:
session.CreateCriteria<TblDocket>()
.Add(Restrictions.Eq(x=> x.DocketNumber, "10101"));
However, this doesn't appear to be the case and I seem to have to write:
session.CreateCriteria<TblDocket>()
.Add(Restrictions.Eq("DocketNumber", "10101"));
That'll be less-than-wonderful when I rename any properties! I've always though hard coded strings in code is bad, especially when the strings relate to property names.
Is there any way I can strongly type these restrictions? I had a look at this blog post, but it seems quite messy, is there a nicer solution?

I decided to use NHibernate.Linq instead. I found a brilliant tutorial here.

You can't using out-of-the-box NHibernate.
There is a project called NHibernate Lambda Extensions which allows you to do this with some limitations.

since NHibernate 3.0 there is also QueryOver available which are a nice typesafe wrapper around the criteria API.
session.QueryOver<TblDocket>()
.Where(x => x.DocketNumber, "10101");

For anyone who comes along this post and doesn't like linq or isn't too familiar with lambda you can still safely use ICrierta's such as
session.CreateCriteria<TblDocket>().Add(Restrictions.Eq("DocketNumber", "10101"));
what you need is helper classes so you can remove the magic strings such as "DocketNumber" so that if you do change your property names or column names these are taken care of for you or will atleast produce a build error so you know before you publish your code.
Anyone wanting to see an example can have a look at NhGen ( http://sourceforge.net/projects/nhgen/ ) and the query examples at https://sourceforge.net/projects/nhgen/forums/forum/1169117/topic/3789112 which show how helpers classes can be used like.
// Find using a simple entity query
IList<IMessage> messageList3 = messageDao.Find( new [] { Restrictions.Le(MessageHelper.Columns.Date, dateLastChecked) } );
Note that this project also created entity wrapper classes which group all your common CRUD methods into one class (xxxDao as show above) so you don't have to keep copying the same code over and over again.

Related

Same business entity for identical tables?

I got a legacy database which have about 10 identical tables (only name differs).
Is it possible to be able to use the same business entity for all tables without having to create several classes/mapping files?
You can use the entity-name feature if you are using NHibernate v2.1 or higher. It is poorly documented but I am actively using the feature. It has gotten hard to find the documentation on it but look here:
Section 5.3 in
http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname
A couple of things to be aware of. You must now use entity-name instead of class name to refer to the objects. In general it is not an entirely transparent change moving from class names to entity names.
Session actions now require two parameters, for example:
_session.Save("MyEntity", myobject)
The entity-name controls what table the data goes into.
Some HQL queries do not work right anymore, sometimes you must use Criteria instead.
If you need a set of sample code I may be able post some, but far too busy at the moment. I suggest you look at the limited info you can find and set it up for a very simple object and multiple tables to learn how it all works. It does work.
You can create a base class with all the properties, but you still need to map them all.
For that, you can either use copy&paste, XML entities (see examle at http://nhibernate.info/doc/nh/en/index.html#inheritance-tableperconcreate-polymorphism), or a code-based mapping method (Fluent or ConfORM). They usually make reuse easier.

Where is the api reference for nhibernate?

I may be going mental, but I can not find any api reference material for nhibernate. I've found plenty of manuals, tutorials, ebooks etc but no api reference. I saw the chm file on the nhibernate sourceforge page, but it doesn't seem to work on any of my PCs (different OSes)
Can someone please point me in the right direction?
I just found this one:
http://web.archive.org/web/20141001063046/http://elliottjorgensen.com/nhibernate-api-ref/index.html
It doesn't seem to be official, but at least it looks like an API reference... unlike the official reference, which mostly describes concepts and mappings without any information about classes and members.
If you're on Windows, get ILSpy and point it at NHibernate.dll. It's not quite the same as real API documentation, but it's not half bad.
There is no class references publicly available on Internet as far as I know. You may build it from the source. Clone them, build the NHibernate.sln solution, then go into doc folder, ensure you have prerequisites indicated in reference\readme.txt file, and run nant doc. This will generate the class reference in the build folder.
Otherwise the most commonly used API are not wide, and most of them are xml documented with intellisens working in Visual Studio. The reference documentation has the advantage of giving more context, probably helping avoiding pitfalls like believing ISession.Update is to be used for updating entities (this is wrong, you do not need it unless you use detached entities, or entities coming from another session).
Official documentation reference is on https://nhibernate.info.
Sub-links:
Global documentation list
Reference (What I mostly use, especially following sub parts.)
Configuration
Mapping - basic / entities. (Add mapping xsd definition file in any or your solution folders for letting VS know it and give you intellisens in your hbm mappings.)
Mapping - collections
Querying - general. Do not miss the named queries feature in The IQuery interface.
Querying APIs:
HQL. I mostly use HQL with named queries, in mappings, for queries not dynamically built. They get parsed and validated when building session factory, which normally occurs at application startup, so it is almost as good as compile time validation. Checks log4net logs to get detailed reasons of named query parsing failures.
Criteria API. I view it as the historical way of dynamically building queries in code, to be preferred over constructing HQL strings.
QueryOver API. Based on Criteia API, with lambda expression support for having compile time validation of queried entities namings. Should be preferred over Criteria API in my opinion.
Linq API. Great for dynamically built queries. Bear in mind that its implementation translates your queries to HQL. With complex queries, it may generate unsupported HQL constructs. Having knowledge of HQL capabilities allows a better understanding of how to write a supported Linq query for complex cases. (By example, for a complex order by, better use an explicit linq sub-query in the OrderBy rather than using a collection mapped on your queried entity.)
Native SQL. Well, quite self-explanatory. To be used by example when you need some SQL special feature not available through other querying APIs (SQL server full-text, select for xml, ...), and that you do not wish to extend those other APIs. You may also call stored procedures. When using native SQL, I favor SQL named queries.
Modifying data, from Updating objects to Flush, and Exception handling.
Performances.
Batch fetching. About this, you may read my post here for a detailed explanation of why lazy loading can be very efficient with NHibernate, thanks to batch fetching. This single feature will always cause me to prefer NHibernate over Entity Framework, till it ceases being lacking in EF.
Second level cache. Another great NHibernate feature, lacking native support in EF. Beware, you must use transactions for leveraging this. It allows NHibernate to automatically evict cached entries for you as you change data through your application process. Without transactions, NHibernate will disable the second level cache as soon as you start changing data, for avoiding letting the cache yield you stale data.
Interceptors. This is one way among many allowing to customize NHibernate inner working. NHibernate is very strong at allowing you to extend it. You may also add your own HQL extensions as here, your own linq2NH extension as here (all are answers from me). And there are other ways, see this list for linq2NH extensibility solutions.
Moreover, a class reference will very likely be near the Hibernate one. There is so many internals APIs supporting its implementation that is not much usable.
Why are such API not hidden (internal, private, ...)? Not hiding them is required for allowing the great extensibility capabilities of NHibernate. Those capabilities are a must have in my opinion. In contrast, it is so hard to fix some other .Net project shortcomings, due to lacks of extensibility they suffer. (MVC FileResult and the TweakDispositionAsInline I had to use instead of just being able of overriding some method, or try extend linq-to-entities, see this.)
there is a good book that covers a lot, and there is the html documentation on the site (which also comes as a book)
(the book would be manning - nHibernate in Action - a little outdated, but a good start)
Here is the link to the online reference

How could nHibernate not be 100% compile time tested?

One thing that bothers me about nHibernate is that it is not 100% compile time tested.
If I rename a column in my database table, and I update the mapping file for that table, when I hit compile I should get errors in all my query code (hql/criteria whatever) of where I referenced that column name and how it is spelled wrong.
The whole point (for me anyway) of using an ORM was that database changes won't break my queries.
In other words, I will be notified at compile time of what needs to be fixed, instead of getting runtime errors etc.
To achieve what you want I think your best solution is to use a combination of Fluent NHibernate and nhlambdaextensions. Fluent NHibernate will give you type-safe checking on your mapping files (so if you change a property on your entity, the compiler will throw an error if you don't also change the property on your mapping class). The lambda function extensions will give you type-safe queries via the Criteria API (not HQL since that's just magic-strings SQL-with-objects).
Also to clarify your question, you said:
If I change a column (rename) in my
database table, and I update the
mapping file for that table, when I
hit compile I should get errors in all
my query code (hql/criteria whatever)
of where I referenced that column name
and how it is spelled wrong.
Just changing the database side should break nothing (assuming you also make the change in your XML mapping file). Your code does not reference the column="first_name" portion of the mapping, it references the name="FirstName" portion. If you do not change your entity, renaming a column (from "firstname" to "first_name", for example) in the database will not break your queries as long as you update your mapping file as well.
You should look at Castle ActiveRecord. I used this before and it allows you to not worry about the mapping files (.hml) as much. It lets you make your changes at the class level definitions, and the mappings files were generally untouched.
If you are writing bad queries, that sounds like a design problem, not an nHibernate problem.
You won't get errors providing the Property names haven't changed, as most people use HQL for their queries in NHibernate.However if you do change the Property names and not the HQL you will indeed get broken queries, e.g.:
FROM User Where User.Surname = 'bob'
Change the Surname property to Lastname and it'll break. It's a feature lacking in NHibernate but would make a good project for the contrib - a Subsonic style query interface. This a project sort of similar but still use HQL.
As mentioned above ActiveRecord and Fluent NHibernate are the closest to type checking with NHibernate. Both enforce that you inherit your classes from their base class, as you'd expect and ActiveRecord is not intended for production use - Ayende has said in a video that's meant to be a prototyping tool for NHibernate.
Hibernate uses dynamic byte code generation to create the mapping classes, based on the mapping configurations.
The fundamental point of ORM is to enable auto-magical mapping (bridge) between Objects and Relational systems. Thus: ORM.
if you want to strongly type your objects rather than using xml config which can cause alot of runtime issues if not properly tested, I would look into FluentNHibernate which has convention maps that allow you to map your classes to data in code. Made my life alot easier especially when first starting with NHibernate wish i had found it before i knew how to properly map using xml
Does NHibernate have the equivalent of the Java version's schema validator? In which case, you could add a step to your build process to build the session factory and run the validator-- building the session factory should also compile named queries, hence validating them too.
Hmm, looks like it supports something like that: http://nhibernate.info/blog/2008/11/22/nhibernate-schemavalidator.html
NB this means your build process will fail to work if your dev database is not available--- which I would regard as a bad thing.

Generate LINQ query from multiple controls

I have recently written an application(vb.net) that stores and allows searching for old council plans.
Now while the application works well, the other day I was having a look at the routine that I use to generate the SQL string to pass the database and frankly, it was bad.
I was just posting a question here to see if anyone else has a better way of doing this.
What I have is a form with a bunch of controls ranging from text boxes to radio buttons, each of these controls are like database filters and when the user hits search button, a SQL string(I would really like it to be a LINQ query because I have changed to LINQ to SQL) gets generated from the completed controls and run.
The problem that I am having is matching each one of these controls to a field in the database and generating a LINQ query efficiently without doing a bunch of "if ...then...else." statements. In the past I have just used the tag property on the control to link to control to a field name in the database.
I'm sorry if this is a bit confusing, its a bit hard to describe. Just throwing it out there to see if anyone has any ideas.
Thanks
Nathan
When programming complex ad-hoc query type things, attributes can be your best friend. Take a more declarative approach and decorate your classes, interfaces, and/or properties with some custom attributes, then write some generic "glue" code that binds your UI to your model. This will allow your model and presentation to be flexible, without having to change 1000s of lines of controller logic. In fact, this is precisely how Microsoft build the Visual Studio "Properties" page. You may even be able use Microsoft's "EnvDTE.dll" in your product depending on the requirements.
You could maybe wrap each control in a usercontrol that can take in IQueryable and tack on to the query if it is warranted.
So your page code might go something like
var qry = from t in _db.TableName
select t;
then pass qry to a method on each user control
IQueryable<t> addToQueryIfNeeded(IQueryable<t> qry)
{
if(should be added)
return from t in qry
where this == that
select t;
else
return qry
}
then after you go through each control your query would be complete and then you can .ToList() it. A cool thing about LINQ is nothing happens until you .ToList() or .First() it.
I don't know about the performance here, but if you set up the LINQ to SQL data context class you should be able to query a database table with a .Select(...) or .Where(...). You should be able to build lambda expressions for either of these dynamically. You might look into dynamic generation of lambda expressions for this purposes. I have done everything up to the point of the dynamic lambda generation, but it is possible.
I'm not 100% sure how to achieve this but I know where a good place to start would be, in the ASP.NET MVC source. In recent versions it is capable of taking the form response and pass it into a helper method which does the writing to a LINQ data source.
I believe MVC is C# so if you're looking for a VB translation you could try using .NET Reflector and converting it back to VB.
I think you are searching how to create a "Dynamic" Linq Query, Here is an example about how to do it with a library of extension methods. Those methods take string arguments instead of type-safe language operators.
I don't mind sfusco's method by using attributes. The only thing that i'm not sure of is where to attach the attributes to because If I attach then to the controls declaration which is in the designer code it will get regenerated when the form changes.
Or am I completely misunderstanding sfusco's methods?
I think perhaps the right way to do this would be an extender provider: MSDN documentation
Then, you can use the editor to provide the field names to hook up with, and your extender provider can be passed an IQueryable<T>, add the criteria, and return an IQueryable<T>.

Best practices for querying with NHibernate

I've come back to using NHibernate after using other technologies (CSLA and Subsonic) for a couple of years, and I'm finding the querying a bit frustrating, especially when compared to Subsonic. I was wondering what other approaches people are using?
The Hibernate Query Language doesn't feel right to me, seems too much like writing SQL, which to my mind is one of the reason to use an ORM tools so I don't have to, furthermore it's all in XML, which means it's poor for refactoring, and errors will only be discovered at runtime?
Criteria Queries, don't seem fluid enough.
I've read that Ayende's NHibernate Query Generator, is a useful tool, is this what people are using? What else is out there?
EDIT: Worth a read
http://www.ayende.com/Blog/archive/2007/03/17/Implementing-Linq-for-NHibernate-A-How-To-Guide--Part.aspx
The thing with LINQ for NHibernate is still in beta; I'm looking forward to NHibernate 2.1, where they say it will finally make the cut.
I made a presentation on LINQ for NHibernate around a month ago, you might find it useful. I blogged about it here, including slides and code:
LINQ for NHibernate: O/R Mapping in Visual Studio 2008 Slides and Code
To rid yourself of the XML, try Fluent NHibernate
Linq2NH isn't fully baked yet. The core team is working on a different implementation than the one in NH Contrib. It works fine for simple queries though. Use sparingly if at all for best results.
As for how to query (hql vs. Criteria vs. Linq2NH), expose intention-revealing methods (GetProductsForOrder(Order order), GetCustomersThatPurchasedProduct(Product product), etc) on your repository interface and implement them in the best way. Simple queries may be easier with hql, while using the specification pattern you may find the Criteria API to be a better fit. That stuff just stays encapsulated in your repository, and if your tests pass it doesn't much matter how you implement.
I've found that the Criteria API is cumbersome and limiting but flexible. HQL is more my style (and it's better than SQL - it's object based, not schema based) and seems to work better for me for simple GetX methods..
I use Linq for NHibernate by default. When I hit bugs or limitations, I switch to HQL.
It's a clean approach if you keep all your queries together in a data access class, such as a Repository.
public class CustomerRepostitory()
{
//LINQ for NHibernate
public Customer[] FindCustomerByEmail(string email)
{
return (from c in _session.Linq<Customer>() where c.Email == email).FirstOrDefault();
}
//HQL
public Customer[] FindBestBuyers()
{
var q = _session.CreateQuery("...insert complex HQL here...");
return q.List<Customer>();
}
}
You asked about refactoring. LINQ is obviously taken care of by the IDE, so for any remaining HQL, it's fairly easy to scan these repository classes and change HQL by hand.
Putting HQL in XML files is a good practice, maybe see if the ReSharper NHIbernate plugin can handle the query refactoring by now?
A big improvement when writing or refactoring queries (HQL or LINQ) is to put finder methods under unit test. This way you can quickly tweak the HQL/LINQ until you get a green bar. The compile/test/feedback loop is very fast, especially if you use an in-memory database for testing.
Also, if you forget to edit the HQL after refactoring, the unit tests should let you know about your broken HQL very quickly.
An alternative to LINQ-to-NHibernate and Ayende's NHQG is to generate NHibernate Expressions/Restrictions from C#3 Expressions. This way you get a more strongly-typed Criteria API.
See:
http://bugsquash.blogspot.com/2008/03/strongly-typed-nhibernate-criteria-with.html
http://www.kowitz.net/archive/2008/08/17/what-would-nhibernate-icriteria-look-like-in-.net-3.5.aspx
http://nhibernate.info/blog/2009/01/07/typesafe-icriteria-using-lambda-expressions.html
scrap nHibernate and go back to Subsonic if you can. In my opinion, Subsonic is a far more fluent and testable ORM/DAL. I absolutely hate HQL what's the point of a weakly typed query in an ORM? And why would I use Linq/nH/SQL when I can just use Linq to SQL and cut out a layer?
nHibernate was a good ORM when Subsonic wasn't around, but now, it's just plain awful to work with in comparison. It easily takes me 2 times longer to do stuff with nHibernate vs Subsonic. Testing is a pain since nHibernate is runtime, so now I need to employ a few QA engineers to "click" around the site instead of getting a compile time error.