views:

196

answers:

2

One of the many reason to use FluentNHibernate, the new QueryOver API, and the new Linq provider are all because they eliminate "magic string," or strings representing properties or other things that could be represented at compile time.

Sadly, I am using the spatial extensions for NHibernate which haven't been upgraded to support QueryOver or LINQ yet. As a result, I'm forced to use a combination of QueryOver Lambda expressions and strings to represent properties, etc. that I want to query.

What I'd like to do is this -- I want a way to ask Fluent NHibernate (or perhaps the NHibernate QueryOver API) what the magic string "should be." Here's a pseudo-code example:

Currently, I'd write --

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects("abc", other_object));

What I'd like to write is --

var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(session.GetMagicString<Shuttle>(x => x.Abc), other_object));

Is there anything like this available? Would it be difficult to write?

EDIT: I just wanted to note that this would apply for a lot more than spatial -- really anything that hasn't been converted to QueryOver or LINQ yet could be benefit.

A: 

Assuming I'm understanding your question what you might want is a helper class for each entity you have with things like column names, property names and other useful things, especially if you want to use ICriteria searches. http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx has plenty of projects that might help. NhGen (http://sourceforge.net/projects/nhgen/) creates very simple helper classes which might help point you down a design path for what you might want.

Clarification Edit: following an "I don't understand" comment

In short, I don't beleive there is a solution for you just yet. The QueryOver project hasn't made it as far as you want it to. So as a possible solution in the mean time, to remove magic strings build a helper class, so your query becomes

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.Abc, other_object));

That way your magic string is behind some other property ( I just chose .Abc to demonstrate but I'm sure you'll have a better idea of what you want ) then if "abc" changes ( say to "xyz" ) you either change the property name from .Abc to .Xyz and then you will have build errors to show you where you need to update your code ( much like you would with lambda expressions ) or just change the value of the .Abc property to "xyz" - which would really only work if your property had some meaningfull name ( such as .OtherObjectIntersectingColumn etc ) not that property name itself. That does have the advantage of not having to update code to correct the build errors. At that point your query could be

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.OtherObjectIntersectingColumn, other_object));

I mentioned the open source project ecosystem page as it can give you some pointers on what types of helper classes other people have made so your not re-inventing the wheel so to speak.

cdmdotnet
I don't really understand your answer... sorry.
David Pfeffer
The answer has been edited as I couldn't clarify it for you in a comment
cdmdotnet
-1er. Could you please explain your downvote?
David Neale
It was prior to the edit.Anyway, this isn't what I'm really looking for but I guess its the best out there.
David Pfeffer
+2  A: 

There is a much simpler solution - Expressions.

Take the following example:

public static class ExpressionsExtractor
{
    public static string GetMemberName<TObj, TProp>(Expression<Func<TObj, TProp>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;

        if (memberExpression == null)
            return null;

        return memberExpression.Member.Name;
    }
}

And the usage:

var propName = ExpressionsExtractor.GetMemberName<Person, int>(p => p.Id);

The ExpressionsExtractor is just a suggestio, tou can wrap this method in whatever class you want, maybe as an extension method or preferably a none-static class.

Your example may look a little like this:

var abcPropertyName = ExpressionsExtractor.GetMemberName<Shuttle, IGeometry>(x => x.Abc);
var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(abcPropertyName, other_object));
Matan
oh, and don't forget to give a more thought out solution as to what to do if the Body isn't a MemberExpression, this was just an example...
Matan