Fluent NHibernate - HasMany mapping with condition - nhibernate

I have a HasMany mapping that needs a condition. I have this partially working, but there's got to be a better way than what I'm doing. The condition I'm using needs to look at a property on another table that I'm joining to. What I have so far is:
HasMany<MetaData>(x => x.MetaData).Table("MetaData")
.KeyColumn("DefinitionID")
.KeyColumn("TableID")
.Where("metadatade1_.SourceTable = 'Providers'")
.Cascade.SaveUpdate();
In the code above, the where clause is referencing "metadatade1_", because it's trying to fully qualify the name, and that is the name NH is generating. I've tried using "MetaDataDefinitions.SourceTable" (MetaDataDef... is the physical table name), and also just "SourceTable" by itself, however none of these worked.
Is there a way to not have it try and fully qualify the name on the condition and just pass "SourceTable='Providers'" OR is there a way I can have it reference the generated name without me having to manually plug it in?

In short, no. The Where method (and respectively the where= attribute in HBM.XML) accept only raw sql, and as such is prone to the problems you're seeing.
Your best option is to not use a collection and instead rely on a query to retrieve your metadata instances.

Related

Refering to a particular parent, in case of multiple, and then retrieving its attribute

If an sobject has more then one parent, how do we lexically refer any one its parent in order to get its attributes?
I need it to write a naming convention for that particular sobject.
The sobject and its parent sobjects are connected in the schema by code.
What I tried was something like:
{project.code}/{sobject.parent01_code}/{sobject.code}/{context}
which works but {sobject.parent01_code} is not what I want, because it is not quite self-explanatory and cryptic to be used for naming of files and directories.
I rather want to something like ../{sobject.parent01.name}/.. or ../{sobject.parent01_code.name}/.. which returns Reported Error: "too many values to unpack" error.
So how can I achieve such a thing? Given, if I am not wrong, the absence of a full brunt expression language in the setting of naming conventions, which, if a present, would enable something like #SOBJECT(parent01["code", {sobject.parent01_code}]).name.
These are two separate questions but put into one because it relates to one particular problem.
This used to be unsolved in earlier versions of tactic. In 4.1 however, you can also use the expression language in the braces.
ex: {project.code}/{#GET(example/some_stype.name)}/versions
If some_stype is the parent of to the current stype's, you'll get the corresponding sobject's name.

Updating SQL from object with groovy

When you read in a result set in Groovy it comes in a collection of maps.
Seems like you should be able to update values inside those maps and write them back out, but I can't find anything built into groovy to allow me to do so.
I'm considering writing a routine that allows me to write a modified map by iterating over the fields of one of the result objects, taking each key/value pair and using them to create the appropriate update statement, but it could be annoying so I was wondering if anyone else had done this or if it'sa vailable already in groovy.
It seems like just a few lines of code so I'd rather not bring in hibernate for this. I'm just thinking a little "update" method that would allow:
def rows=sql.rows(query)
rows[0].name="newName"
update(sql, rows[0])
to update the first guy's name in the database. Anyone seen/created such a monster, or is something like this already built into Groovy Sql and I'm just missing it?
(I suppose you may have to point out to the update method which field is the key field, but that's doable...)
Using the rows method will actually read out all of the values into a List of GroovyRowResult so it's not really possible to update the data without creating an update method like the one you mention.
It's not really possible to do that in the generic case because your query can contain joins or a column reference that is an aggregate, etc.
If you're selecting from a single table use the Sql.eachRow method however and set the ResultSet to be an updatable one, you can use the underlying ResultSet interface to update as you iterate through:
sql.resultSetConcurrency = ResultSet.CONCUR_UPDATABLE
sql.resultSetType = ResultSet.TYPE_FORWARD_ONLY
sql.eachRow(query) { row ->
row.updateString('name', 'newName')
row.updateRow()
}
Depending on the database/driver you use, you may not be able to create an updatable ResultSet.

NHibernate: Is it possible to add restriction based on alias name

Say I create a criteria query and transform it with the AliasToBean result transormer.
session.CreateCriteria<Staff>("s")
.CreateAlias("supervisor", "super")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("s.name"), "name")
.Add(Projections.Property("super.name"), "supervisor_name"))
.SetResultTransformer(Transformers.AliasToBean<StaffView>());
Is it possible to add a restriction when you only know the property name of the bean? You can AddOrder using the bean property names but the Restrictions only appear to work with the actual property name. I'm guessing this is because they are applied before the transformation, much like you don't use a column alias in a where clause but you can in the order by.
//throws exception like cannot find property supervisor_name in Staff class
//only "super.name" works
.Add(Restrictions.Like("supervisor_name", "blah"))
//this works though
.AddOrder(Order.Asc("supervisor_name"))
So basically I need a way to get the aliased property name based on the alias. I can think of multiple ways to do this, but I was hoping NHibernate had some existing method? I could for example keep a separate map of the property to alias names or just map to a database view so there is no need to transform to bean.
It should work with name of alias dot property name.
{alias}.Name.
Or am I misunderstanding your problem?

NHibernate Projection using SqlQuery

I'm trying to reproduce the HqlQuery style 'select new ObjectToProjectOut' functionality. i.e. take a list of columns returned from a query and return as a list of ObjectToProjectOut types that are instantiated using a Constructor with as many parameters as the columns in the query.
This is in effect what 'select new ObjectToProjectOut' achieves in Hql.... but clearly that's not available in SqlQuery. I think I need to set a result transform and use either PassThroughResultTransformer, DistinctRootEntityResultTransformer etc to get it to work.
Anyone know what I should use ?
ok.... after looking at the NHibernate code it seems that I was looking for AliasToBeanConstructorResultTransformer.... of course!
However I may have found an nHibernate bug. If you have the same column name returned twice from two different tables (market.name and account.name, say) then by the time nHibernate returns the array from the db to the transformer, the first occurance of 'Name' will be used for both. Nasty.
Work around is to uniquely alias. With Hql, the sql generated is heavily aliased, so this is only a bug with SqlQuery.
Grrrr. Today must be my day, also found another nHibernate bug/issue I've posted to StackOverflow for comment.
You could use the AddEntity method to fill entities from a SQL query.
Here are two examples from the NHibernate docs:
sess.CreateSQLQuery("SELECT * FROM CATS")
.AddEntity(typeof(Cat));
sess.CreateSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS")
.AddEntity(typeof(Cat));

NHibernate: Return A Constant In HQL

I need to return a constant from an HQL query in NHIbernate
SELECT new NDI.SomeQueryItem(user, account, " + someNumber + ")
FROM NDI.SomeObject object
I am trying for something like above. I've tried this:
SELECT new NDI.SomeQueryItem(user, account, :someNumber)
FROM NDI.SomeObject object
And then later:
.SetParameter("someNumber", 1).List<SomeQueryItem>();
But in the first case I get a 'Undefined alias or unknown mapping 1'. Which makes some sense since it probably thinks the 1 is an alias.
For the second I get a 'Undefined alias or unknown mapping :someNumber' which again makes some sense if it never set the parameter.
I have to believe there's some way to do this.
Please feel free to continue to believe there is some way to do this - but with HQL there isn't!
Why would you want to anyway? If you want to update the value this property to the value you specify, then do so after you've loaded the objects. Alternatively, if your result set doesn't quite match to your objects, you could alway use a SQL query (which you can still do via an NHibernate session). But the purpose of NHibernate is to map what's in your database onto objects, so specifying a manual override like this is quite rightly not allowed.
It sounds like there is a (small?) disconnect between your domain objects and your database model. What about creating a small "DTO" object to bridge this gap?
Have your query return a list of SomeQueryItemDTO (or whatever you want to call it) which, due to the naming, you know is not a true part of your domain. Then have some function to process the list and build a list of true SomeQueryItem objects by incorporating the data that is extraneous to the database.
If you're already using the Repository Pattern, this should be easier since all the ugly details are hidden inside of your repository.