Fluent Nibernate putting a where clause in the mapping - nhibernate

I've got two objects a parent and a child list. In my fluent nhibernate mapping for the parent I want to load the list of the children.
However I want this to be conditional, a column in the child table is called "IsDeleted" and I only want to return the children where "IsDeleted" is false.
Is it possible to set up a mapping to do this? If not is it possible to do it in just standard nhibernate?
Thanks

Yes, you can use a Where constraint in Fluent NHibernate to map this. Somehting like:
HasMany(x => x.Children).Where("IsDeleted = 0");
The Where constraint should use SQL syntax not HQL. For tables that allow soft deletes it's probably easier to map a view that filters the deleted records out.

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?

Fluent Nhibernate --- How to make it NOT update the other table

I have a [User] table/class and a [Company] table/class and there is a link-table [UserCompany] between them.
When editing a User, beside basic information people also could change that user's access Companies, so I do the map like this in UserMap.cs:
HasManyToMany(u => u
.Companies)
.Cascade.SaveUpdate()
.Table("UserCompany")
.ParentKeyColumn("UserId")
.ChildKeyColumn("CompanyCode")
.Not.LazyLoad();
Also in CompanyMap.cs I set inverse like this:
HasManyToMany(c => c.Users)
.Inverse()
.Table("UserCompany")
.ParentKeyColumn("CompanyCode")
.ChildKeyColumn("UserId");
The problem now is: I could update [User] information/table, plus the linking data in [UserCompany] table. However, the Fluent Nhibernate also update the [Company] table which I don't need at all.
Is there any way I could let FN not update Company table?
To stop cascading updates just remove the
.Cascade.SaveUpdate()
from your Many-to-many mapping.
It could be a bit confusing. In comparison with the cascading used on <list>s and <map>s. In that case, the update is done directly on the child table (parent has more children... child contains the ParentId - cascade is reasonable to do operation on the child record)
But here we are working with a pair table. The relation is stored there. And this table will be always managed by NHibernate (implicit cascading).
The setting .Cascade.SaveUpdate() goes to other end of the many-to-many relation. To company table in our case. It could be handy.. but you can omit that and get everything running as expected.

NHibernate One-to-Many - why is it updating child with null foreign key?

I am troubleshooting code that is attempting to update a disconnected entity that has uninitialized references to child entities. The intent is to update only the properties on Parent without loading children.
HasMany(x => x.ChildEntities)
.KeyColumn("ChildEntityId")
.Table("ChildEntity")
.Not.LazyLoad()
.Inverse()
.Cascade.All().AsBag();
When Session.Update(parent) is called, two update statements are executed. The first updates the parent object as expected.
update Parent set ... where ParentId = 12345
The second update confuses me...
update ChildEntity set ParentId = null where ParentId = 12345
Why is NHibernate issuing that second SQL statement? I realize that ChildEntities is uninitialized and that NHibernate is probably trying to enforce the state of Parent but I can't seem to tweak the mapping to not make this second update. I've tried Merge, lazy loading, various cascade options, etc. without success. The only connected entity in the session when it tries to commit is Parent.
Note that I typically approach this by retrieving the entity with lazy loading enabled and then mapping from the disconnected object (DTO or entity) to the connected entity before letting NHibernate persist to the database. I want to understand why the above isn't working before I suggest an alternative approach.
This was annoying.
A quick search through the NHibernate source for "could not delete collection" showed up in a block that could only execute if !isInverse (AbstractCollectionPersister.cs). That drew my attention because the mapping code was explicitly setting Inverse on that collection.
If Inverse is false and the collection is empty, NH executes an update on the child table setting the foreign key to null where the foreign key equals the parent id.
Fluent is configured to auto-map all entities in a given namespace. The assumption was that anything with a manual mapping would be ignored by auto mapping. A quick check of the hbm.xml files produced by Fluent confirmed that Inverse was not being set. I added Parent to the list of entities that were explicitly excluded from Auto Mapping and everything started working.
.IgnoreBase<Parent>()

NHibernate - use WHERE clause on one-to-one mapping

Is it possible to somehow restrict a one-to-one mapping with a constraint other than property ref? Ideally, something along the lines of the class definition, for example, where you can add where="Condition=Value".
Thanks
You can use nhibernate filters for this: http://nhibernate.info/blogs/nhibernate/archive/2009/05/04/nhibernate-filters.aspx

NHibernate mapping: one-to-many where

I need to restrict a one-to-many collection by a date column with a value specified on the parent element. The 'where' attribute on set or bag looks perfect for this.
NHibernate documentation describes the 'where' attribute as being for arbitrary SQL, so am I correct in assuming that I cannot use values from the parent class here as I would in HQL and must implement my own IUserCollection instead?
IMHO using a filter would be better because you could write the restriction in database agnostic HQL.