To all interested, I wrote a reusable/generic transformer that lets me
write type-safe code like:

Session.QueryOver<Tenant>()
                                .Select(x => x.Id, x => x.FirstName, x
=> x.LastName)
                                .UnderlyingCriteria.SetResultTransformer(new
PartialObjectTransformer<Tenant>(x => x.Id, x => x.FirstName, x =>
x.LastName))
                                .List<Tenant>()


The code for the transformer is as follows:


        public class PartialObjectTransformer<T> : IResultTransformer
        {
                private readonly List<PropertyInfo> _properties;

                public PartialObjectTransformer(params Expression<Func<T, 
object>>[]
properties)
                {
                        _properties = new List<PropertyInfo>();
                        foreach (var property in properties)
                        {
                                Expression body = property;
                                if (body is LambdaExpression)
                                {
                                        body = ((LambdaExpression)body).Body;
                                }
                                switch (body.NodeType)
                                {
                                        case ExpressionType.Convert:
                                                _properties.Add((PropertyInfo) 
((MemberExpression)
((UnaryExpression) body).Operand).Member);
                                                break;
                                        case ExpressionType.MemberAccess:
                                                _properties.Add((PropertyInfo) 
((MemberExpression)
body).Member);
                                                break;
                                        default:
                                                throw new 
InvalidOperationException();
                                }
                        }
                }

                public object TransformTuple(object[] tuple, string[] aliases)
                {
                        var instance = Activator.CreateInstance(typeof(T));
                        for (var i = 0; i < tuple.Length; i++)
                        {
                                _properties[i].SetValue(instance, tuple[i], 
null);
                        }
                        return instance;
                }

                public IList TransformList(IList collection)
                {
                        return collection;
                }
        }


Disclaimer, I don't know if this is ideal or will work for you, but it
works on my box.  :)




On May 9, 4:20 pm, Jim Geurts <[email protected]> wrote:
> Thanks for your help with this Richard.  I look forward to see what
> comes in the future for easier aliases.  In the mean time, I'll look
> into using a DTO and custom transformer that Ayende mentioned 
> here:http://ayende.com/Blog/archive/2007/08/26/Partial-Object-Queries-With...
>
> Thanks again,
>
> Jim
>
> On May 9, 5:02 am, "Richard Brown \(gmail\)" <[email protected]>
> wrote:
>
>
>
>
>
> > Hi Jim,
>
> > > If the NH dev team recommendation
> > > is to use linq to cast the object array to the intended object type ...
>
> > That was a suggestion.  If you want the mapped type, the recommendation
> > would be to retrieve it directly without projections:
>
> > Session.QueryOver<Tenant>()
> >     ...
> >     .List();
>
> > > Having the API return an object array, when it *knows* the type of object
> > > ...
> > > fail to see why queries with the QueryOver api and projections
> > > wouldn't use the same method that NH uses to populate full objects.
>
> > The API can't know which object you are wanting as soon as you use
> > projections.  The API allows arbitrary projections, so all bets are off on
> > the return type.
>
> > Incidentally, while there's no restriction to prevent you trying to manually
> > create partial Tenant objects, projections/result-transformers are more
> > typically use to create arbitrary non-mapped types (e.g., DTOs), not mapped
> > types.
>
> > If you simply return the complete objects directly (without projections)
> > then the query will "use the same method that NH uses to populate full
> > objects."
>
> > > Also, I did try to use a ResultTransformer, but was unsuccessful:
>
> > You need to alias each of the projections.  I gave it a try with the
> > QueryOver API, and there isn't an easy way of doing this yet.  I'll have a
> > look at making it easier to alias so you can write:
>
> > Tenant tenantAlias = null;
> > Session.QueryOver<Tenant>()
> >     .Select(list => list
> >         .Select(t => t.FirstName).WithAlias(() => tenantAlias.FirstName)
> >         .Select(t => t.LastName).WithAlias(() => tenantAlias.LastName))
> >     .SetResultTransformer(Transformers.AliasToBean<Tenant>())
> >     .List<Tenant>();
>
> > For now, your best bet is probably to write your own IResultTransformer, or
> > simply return the full objects.
>
> > I hope that helps.
>
> > Richard
>
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "nhusers" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to 
> > [email protected].
> > For more options, visit this group 
> > athttp://groups.google.com/group/nhusers?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "nhusers" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group 
> athttp://groups.google.com/group/nhusers?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to