I've been utilizing NHibernate 2.0.1.4000 on all current .NET 3.5 SP1 projects and have had no problems with any other queries (utilizing either the Query or Criteria APIs), until some new business logic dictated the necessity of a new query in this particular project against the application's database that needs to retrieve records with a specific null property (of type DateTime) from a single table.
Knowing that you cannot use the not-equal restriction for this type of query, but instead can use the IsNull restriction, this simple query generates a "Value cannot be null!" Exception when executed. I have extensive DEBUG mode log4net log files, which I have reviewed and haven't yet helped, and I have verified that my class for the table does specify the property I'm checking for is a nullable property (DateTime?) to avoid the problems that can cause by forcing updates to the record, etc., which isn't happening here...
Here's the query, nothing complex, and I've tried with/without the MaxResults additional restriction to eliminate it as a problem, and yet, everytime, the exception gets thrown before I can collect the results:
ICriteria criteria = session.GetISession().CreateCriteria(typeof (Order)).Add(NHibernate.Criterion.Restrictions.IsNull("ShippedOn")).SetMaxResults(10);
IList<Order> entityList = criteria.List<Order>();
Any ideas or pointers to more information that might help me solve this? I've tried using HQL alternatively, same problems... Am I missing something here with regards to returning records with a specific null property?
Quick update...but it turns out after further investigation, that the Expection is actually being thrown when the transaction and unit of work is complete, and the session .Flush() method is called, and again somehow relates to how NHibernate tries to deal with a nullable table field/DAO property. Which even though I've handled in my class and mapping for the applicable table, the actual SQL my criteria with restrictions is generating, causes the exception to be thrown on Flush by a SqlDateTime issue...
For now, my workaround has been to retrieve records from my first restriction and handle the IsNull check in the code instead of the query. Not as performant, but until I figure it out, it's working...
DateTimes are not nullable in .net. Have you tried changing your domain model to use DateTime? which is nullable?
You can get similar exceptions using criteria queries. Suppose I have a Person domain object with a string property called Name. I can construct the following criteria:
ICriteria criteria = session.CreateCriteria(typeof(Person)
.Add(Restrictions.Eq(1234))
however is I list this criteria NHibernate will throw a type mismatch exception because I'm testing a string against an int. Behind the scenes NHIbernate does some clever reflective type checking on the mapped objects and will throw exceptions if the types don't line up. (you'd probably get a SqlException if it wasn't this clever)
I've seen this kind of exception before when there's a mismatch between your domain model, mapping, and database. For example if you have a nullable DateTime field in your database, but not a nullable property on your model.
I described it in a post on my blog a while back. I can't say for sure this is your issue, but it certainly sounds familiar.
Related
I have a table, CityComplete, with columns "USPSCITY", "STATE" and "ZIPCODE"
I have an existing SQLQuery that distinctly selects USPSCITY and STATE based on a fuzzy search. However, when I call list() I get an exception:
19. ResultSet.getString(ZIPCODE)
java.sql.SQLException: Column 'ZIPCODE' not found.
The SQLQuery's entity is set to the CityComplete object.
Is there any way to have Hibernate not try and get ZIPCODE, or have it be part of the result set in some way?
What's the best way to resolve this, other than using Criteria, setting a virtual column with null data, or just getting a full result set and handling distinction on the code side?
When you perform a regular Hibernate query (HQL or Criteria), Hibernate will try to map the resultset based on the properties of the entities which you specified in the mapping. If you are not bringing the "promised" data from the database, you'll need to handle the mapping by yourself, using a ResultTransformer. In this case, you'd still use your CityComplete, but they will be without a ZIPCODE. Unfortunately, there's not much documentation about how to use a ResultTransformer, but you can take a look at the Hibernate's JavaDoc and see if there's one that you could use. If not, you'd need to implement your own:
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/transform/ResultTransformer.html
im pretty confused about lambdas and actually im not even sure i need them here
what im trying to do here is write a function that will return an object from a certain table with a certain criteria
so lets say i can write
function GetRecord(TableName as string,Criteria as string) as object
'do the linq-stuff
end function
now i dont care if the paremeters are strings or lambdas or whatever, but the end result must be that at runtime i dont know which table and which criteria will be used
as sometimes i need to get a customer record by email and sometimes a product by id etc.
if possible i would prefer returning a list of matching objects and then i would just use .firstordefault when i want 1 (such as by id...)
thank you , as always, for taking the time to read this and answer!
all the best
Have you considered using Dynamic LINQ?
Example:
Parsing an expression tree can be a challenging but rewarding method of solving this issue. I think it's overkill and I'd go with Dynamic Linq as decyclone mentioned.
A benefit of parsing the expression tree, however, is that you can have compile time checking of the submitted criteria.
Here are some articles that helped me.
How to: Implement an Expression Tree Visitor: http://msdn.microsoft.com/en-us/library/bb882521(VS.90).aspx
Building a custom IQueryable Provider: http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
Walkthrough: Creating an IQueryable LINQ Provider: http://msdn.microsoft.com/en-us/library/bb546158(v=VS.90).aspx
Expression Tree Basics:
http://blogs.msdn.com/b/charlie/archive/2008/01/31/expression-tree-basics.aspx
I have a collection mapped as a query only property following Ayende's example. My mapping is:
HasMany<Employee>(Reveal.Member<Company>("_employees")).Access.None();
This worked fine, except when I load a Company the foreign key Employee.CompanyId is updated to null. This occurs even if I don't update Company and the generated SQL only includes the CompanyId in the update list even though I have not mapped Employee to update changed properties only.
I tried using NoOp (they're synonyms I think) and declaring the employees collection as a public property instead of a private field. I was finally able to fix it by changing the mapping to:
HasMany(Reveal.Member("_employees")).Access.None().Not.KeyUpdate();
What is the purpose of KeyUpdate and what is the equivalent XML mapping? Why is it needed for a query only property? My assumption was that setting access to none or noop would prevent any changes.
Jamie
You can generate the hbms from your AutoPersistenceModel and have a look at the xml if you are still interested. Just something like
model.CompileMappings();
model.WriteMappingsTo(outputDir);
As an aside, have you had a look yet # ConfOrm. I suspect this will gain increased traction given the dev, but haven't spent much time with it yet.
HTH,
Berryl
I know about the not-null attribute. Is there one for enforcing the minimum length of a string property? I don't want empty strings in my database.
I don't know of anything in the mapping file that will let you do this (and I don't see anything in the schema). You could probably define a custom type using NHibernate.IUserType and build your logic into that type (if the string is empty save null). Here is an example of building an IUserType (it would be easy to change this example code to work for you)
The other option is to take advantage of NHibernate.Validations and to handle the validation logic before getting to the point where you are saving the entity to the database.
You are looking for NHibernate Validator! There's a blog post here showing some of its goodness.
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.