I have the following domain model:
public class Name
{
private readonly string fullName;
public Name(string fullName) { this.fullName = fullName }
public string FullName { get { return fullName; } }
public string FirstName { get { /* ... */ } }
public string MiddleNames { get { /* ... */ } }
public string LastName { get { /* ... */ } }
public static implicit operator Name(string name) { /* ... */ }
}
public class Person
{
public Name BirthName { get; set; }
public Name Pseudonym { get; set; }
}
I implemented IUserType
so I can map each name to a single database column with the full name.
Queries like this work:
var people = session.QueryOver<Person>()
.Where(p => p.Name == "John Doe")
.List();
But I can't query like this:
var people = session.QueryOver<Person>()
.Where(p => p.Name.LastName == "Doe")
.List();
Can I make NHibernate work with this?
I'm not much of a nhibernate user, but analyzing all the information we have here about the scenario, I have a strong feeling that the answer is you can't.
You are mapping the value contained in that class to a single value in the db.
For it to allow querying on its pieces, it'd have to understand how all those sub pieces of information in the Name class are related to the full value.
That'd mean understanding what the custom c# code you have there is doing.
update 1:
Above answer is regarding having it all automatically generated for you And using the exact query you mentioned there.
You can definitely work around the problem like suggested by @cs. That is, defining an user defined function that does what you want, and mapping that in nHibernate.
At the very least that'd allow you do do something like:
session.QueryOver<Person>()
.Where(p => session.PersonLastName(p) == "Doe")
.List();
Another way would be to define an extension method that is translated to what you want, implementing it like in this article: http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
Usage then would be like:
session.QueryOver<Person>()
.Where(p=> p.Name.LastNameExt() == "Doe")// Ext just to avoid name collision
.List();
Finally, I'm not sure if it's possible to map the sub properties to user defined functions for each, so that your query can remain unchanged like:
session.QueryOver<Person>()
.Where(p => p.Name.LastName == "Doe")
.List();
Not that in all cases you are changing from concatenating data to parsing data. You are the only one to know if that is really buying you anything, vs. keeping the properties separately.
I believe it's possible, but will require some work on the SQL side of things. The first thing I would probably try is to create a UDF of some sort that will split up the name for you and do the necessary comparison. You can then extend NHibernate to map to this UDF and you should be able to invoke this function from your query, whether it's SQL, HQL, or ICriteria based.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With