NHibernate Query Generation - nhibernate

Some of the NHibernate queries are forming as below, I am just using the NHinernate Map files
select installmen0_.Index as Index1_,installmen0_.accountnumber from Account installmen0_
where installmen0_.accountstatus = 'active'
but I do not have any column called "Index" either in DB table or Map file, Where is NHibernate picking up this column? Please, sujjest where I might be wrong

it is the default columnname for list indexes. Probably you have mapped in Fluent Hasmany(...).AsList() or in xml <list name="mylist"></list>. it is used to persist the index of the element in the list. If you dont care in which order they are in the collection then use Hasmany(...).AsBag() or <bag name="mylist"></bag>

Related

Fluent Mapping Many-Many with sorting

I'm trying to get a many to many relationship to work using Fluent Nhibernate.
I have a Product and a RelatedProduct Table
Product {Id, Name...}
ProductRelated{Id, ProductId, RelatedProductId, relOrder}
and a Product class
The mapping looks like
HasManyToMany(x => x.RelatedProducts)
.Table("ProductRelated")
.ReadOnly()
.ChildOrderBy("relOrder asc")
.ParentKeyColumn("ProductId")
.ChildKeyColumn("RelatedProductId");
When a query is done for Product and the RelatedProducts are lazy loaded I can see that the sorting is applied correctly using the relOrder on the join table.
Session.Query<Product>()
.FetchMany(p => p.Categories)
.FetchMany(p => p.Departments)
Once I add in eager loading of the related products NHibernate tries to sort by a relOrder column on the product itself instead of on the join table.
Session.Query<Product>()
.FetchMany(p => p.Categories)
.FetchMany(p => p.Departments)
.FetchMany(p => p.RelatedProducts)
Any ideas of whats going on here?
Well to answer your question what's going on here?, I would say, you are using: "not-together fitting features" of NHibernate.
A snippet from documentation 6.6. Sorted Collections:
Setting the order-by attribute tells NHibernate ...
Note: that lookup operations on these collections are very slow if they contain more than a few elements.
Note: that the value of the order-by attribute is an SQL ordering, not a HQL ordering!
So, this could be applied only for "standard" lazy loading, becuase this kind of a feature is applied only on a DB side. It is not managing order in the memory.
And the eager fetching, as the counter-part, is a different way how to generate and issue the SQL Statement to DB.
So, eager and order-by will never work together.
*
My NOTE: I simply have to append this. I can't help myself
I.
The Eager fetching is the feature which should be avoided (I never use it, but it's me). There is a better solution and it is setting the BatchSize(), which will reduce the 1+N into 1+(a few) and will keep all the (lazy) featrues, including order-by. Check these if interested:
NHibernate QueryOver with Fetch resulting multiple sql queries and db hits
Is this the right way to eager load child collections in NHibernate
https://stackoverflow.com/questions/18419988/
BatchSize() is supported for HasManyToMany as well: ToManyBase:
/// <summary>Specify the select batch size </summary>
/// <param name="size">Batch size</param>
public T BatchSize(int size) { ...
II.
The many-to-many mapping, while fancy at first look, is not the way I'd suggest. Try to rethink your model and introduce the first-level-citizen: PairingEntity - for the pairing object. It will then use many-to-one and one-to-many mapping which could give us more... e.g. improved querying like Subqueries... try to check these:
How to create NHibernate HasManyToMany relation
many-to-many with extra columns nhibernate
Nhibernate: How to represent Many-To-Many relationships with One-to-Many relationships?

Nhibernate list mapping with not continuous index column

I am developping a ASP.NET with VB using NHIBERNATE to map the tables of a pre-existing database (SQL Server 2005). I have a many-to-many relationship between to entities, that I map like this:
<list name="PropName" table="TableHoldingRelation" lazy="false" >
<key column="idEntity1"></key>
<index column ="orderingColumn" ></index>
<many-to-many class="Entity2" column="idEntity2"></many-to-many>
</list>
The mapping works perfectly and the list(of Entity2) its ordered by the selected column.
The problem is that this column is not continuous, as there might be some values missing (ie: 0,1,3,8). NHibernate is leaving those spaces as null/nothing elements. I would want to have the list "compacted", only containing existing elements, ordered by that column.
Can I achieve this without having to update the database? (updating is not a good solution as it probably will happen in the future that some elements get removed)
Thanks in advance for your help.
EDIT: A bit more info in the problem.
The tables/entities in this case refer to Menus and MenuItems. The application that I am working is is a very complex website, with lots of diferent roles. Each role has his unique menus congfiguration, with their unique items. There are even single users with unique settings. My task is to rewrite the .NET clases and mappings, as they are really messy and other things not relevant for this question. So the database design I am mapping is (for this question, obviously there are other tables):
One table holding menus and their attributes(like wich role do they correspond to)
One table holding menuitems and their attributes (like a link they point to)
One table holding de relation menu-menuitem and a "position"/order column inside that menu.
Just in case more insight on the problem was needed.
As you can read here NHibernate Mapping - <list/> - by Ayende, this behaviour is by design. An extract from comments (close to your question):
...Because in general, having NH doing something like that for you can be
bad. There is a meaning to null values.
But broadly, it is because it is not the responsibility of NHibernate
to do so. If you want something like that, you don't need a list, you
need an ordered set...
With this we can try to change your mapping (see the order-by attribute):
<bag name="PropName" table="TableHoldingRelation"
order-by="orderingColumn"
lazy="false" >
<key column="idEntity1"></key>
<many-to-many class="Entity2" column="idEntity2"></many-to-many>
</bag>
But, this mapping won't allow you to insert into that column orderingColumn.
This documentation 24. Best Practices says:
Don't use exotic association mappings.
Good usecases for a real many-to-many associations are rare. Most of
the time you need additional information stored in the "link table".
In this case, it is much better to use two one-to-many associations to
an intermediate link class. In fact, we think that most associations
are one-to-many and many-to-one, you should be careful when using any
other association style and ask yourself if it is really neccessary.
So, maybe introduce the man-in-the middle pairing object, put the management of the OrderBy property there, and use the sorted list..

Nhibernate many-to-one problem

I've got a problem with mapping many-to-one in the following code:
...
<property name ="CustomerID"/>
<!-- Many-to-one mapping: Customer -->
<many-to-one name="Customer"
class="Customer"
column="CustomerID"
insert="false" update="false"/>
<property name="Date" />
...
You may notice that i have mapped two CustomerID to Customer table. The reason i do this because when i want to create an Order, i just only assign value to CustomerID and other require fields then do save. many-to-one mapping, I just want to get detail of each customerID.
But, the problem is that: after i update customerID of an Order and Executre SaveOrUpdate with Session.Flush() also (I'm using HibernateTemplate), i still got the old figure when accessing to Order.Customer.
i.e:
Order = getOderByID(1);
Order.CustomerID=3 // Suppose value of CustomerId is 1. Now I changed to 3
SaveOrUpdate(Order);
Print(Order.Customer.CustomerID)// it returns 1 which is wrong. It should be 3
Pls help...
Thanks,
I would suggest you to look at this problem from an NHibernate point of view. And not from a relational database view. Let me start with what i feel you should be doing.
var customer = session.Load<Customer>(3);
var order = session.Load<Order>(1);
order.Customer = customer;
//assuming this is a one directional mapping. otherwise you might
//have to do some more steps to disassociate the order from the old
//customers collection and add it to the new customers collection
session.SaveOrUpdate(order);
Now, order.Customer.CustomerID will return 3.
As Serkan suggested, its better and more feasible to work with objects instead of primary keys.
Also, there really shouldnt be any performance impact here. Nhibernate is able to proxy a lot of the associations as long as the classes have virtual public methods. Because of this, as long as you only query for the Id of the customer, it will not generate a separate sql query. The Id is already there with the proxy object.
With regards to the original question, I have a hunch. NHibernate dynamically generates the sql query for the update and the inserts. This case here is of an update. You have explicitly set the CustomerID property to 3. But the Customer property of the order object still points to the customer object with Id 1. So, when NHibernate generates the sql query, it trys to set the value first to 1, as you asked it to. Then it also sees that the Customer is still pointing to the old object, so reset the CustomerId property to 1. I think NHibernate is getting confused with the dual mappings.
There are two things that you can do. First enable the "show_sql" property in the NHibernate configuration.
<nhibernate>
...
<add key="hibernate.show_sql" value="true" />
</nhibernate>
Check what is the sql being generated when you save the order. That will explain things better.
Second, after saving the order, do session.Refresh(order); You can read about the Refresh() method here. Its towards the end of the section 9.2. It will reload the order object with fresh values from the database. Calling order.CustomerID should show what value you have stored in the database.
I think you'd feel much happier in the long run if you try to forget about Id's of entities once you are done with the OR mapping. You are in a different level which you should think in objects only. If I were you I would remove CustomerId property all together.
If you have performance issues try to solve them in NHibernate way, caching etc.
Two things to try
Flushing the session via Session.Dispose if it's NH 2.x otherwise use Flush()
Make your IDs client assigned.
NHibernate will create the IDs for you and try to manage them unless you specifically tell it not to.

Select partial data from a DB table using nhibernate

i have a complex entity, very very heavy.
i want to select only the id and the name of this entity from the db for a better performance.
how do i do that with nhibernate (or fluent nhibernate).
There are a few different possibilities.
Create a New Entity
One possible solution is to create a new entity and map it to the same table, but only map the columns that you want (id and name). This is quite flexible and lets you use that entity as any other entity. The problem is that you introduce some duplication.
Using HQL
Another solution is to use projections. With HQL you can use the select clause to specify which columns to retrieve. If you want a proper entity instance as the result from the query and not an array of objects, you can create a custom constructor for your class and use that in the HQL query.
session.CreateQuery("select new Foo(f.Id, f.Name) from Foo f").List<Foo>();
Using the Criteria API
If you want to use the Criteria API instead of HQL, you can use the SetProjection method. If you want a proper entity from the query and not an array of objects, you can use the AliasToBean result transformer.
session.CreateCriteria(typeof(Foo))
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Name"), "Name")
.Add(Projections.Property("Id"), "Id"))
.SetResultTransformer(Transformers.AliasToBean(typeof(Foo)))
.List();
The criteria example code is borrowed from the following question, which might be of interest:
NHibernate - Only retrieve specific columns when using Critera queries?
You have 2 choices :
when using ICriteria - use (syntax might not be correct but you get the picture)
SetProjections(Projections.ProjectionList.Add(Projections.Property("prop"))
.Add(Projections.Property("prop1")))
when using hql
select c.Col1,c.Col2 from table c
Both of them will return a list of array lists - or something like that - you then have to traverse it and build your .. dictionary (or whatever you have).

Map dynamic/generic properties with NHibernate

I have a scenario where I have a propertybag of key/values that would look something like:
Entry 1 : key="Load", value="2", type="int"
Entry 2 : key="DailyStatus", value="0", type="bool"
I am trying to figure out if it's possible with nhibernate to map these values to a single table that I can pull out at a later time into .net simple types.
I am trying to avoid creating classes to contain all of this data as it can be very repetitive and doesn't allow portions of the application to be as flexible as possible. I had considered storing it in XML or JSON, but this data has to be queried against on a pretty regular basis.
Has anyone mapped dictionaries of simple types to a table in nhibernate and pulled the data back out? I suppose mapping to a generic dictionary would work:
IDictionary<string, IDictionary<object, Type>>
I can do it by hand, but if there is a builtin way for nhibernate to accomplish it that would be easier.
How about you create a class "Triplet" with attriutes id, key, value, type and then map it to a table called whatever you want?