2

Closed

Boolean value column sorting or filtering exception

description

I have a ViewModel with a boolean column mapped to an entity that's a Flag field, which means it can be "N", "Y", or NULL. I try to either sort or filter on the column. I'm using NHibernateGridCustomBindingHelper version 0.5.1 and when I call gridHelper.BuildGridModel(); I get the following exception thrown by the helper:

This expression is not supported: s.EnabledFlag.Equals("Y")

EnabledFlag is the correct property name in the entity, so what's the problem?
Closed Mar 19, 2012 at 1:45 AM by Luis_Fernando

comments

Luis_Fernando wrote Mar 8, 2012 at 10:40 PM

I have some ideas to implement this, maybe something like AutoMapper's "Custom value resolvers": https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers

Luis_Fernando wrote Mar 8, 2012 at 10:42 PM

Just to inform, a boolean could never be equal to "Y" because it is a string.

Noyabronok wrote Mar 9, 2012 at 1:15 PM

I understand that a boolean can't be equal to a string. That doesn't seem to be the problem here. I have a mapping as follows:
---- .ForMember(lvm => lvm.Enabled, m => m.MapFrom(s => s.EnabledFlag.Equals("Y")))
  • lvm.Enabled is boolean property in the ViewModel
  • s.EnabledFlag is a string in the Entity
I am not sure if this scenario is supposed to work by design. I'm confused by the error message, which says that EnabledFlag.Equals("Y") is not a supported expression, but I don't see anything wrong with that expression. Maybe the error message is trying to say that I can't map from a boolean to a string?

Noyabronok wrote Mar 9, 2012 at 2:20 PM

So I have a solution. While it's elegant, it's sort of a workaround since it completely bypasses the helper. Instead of doing the mapping with AutoMapper, I do the mapping with nHibernate. Here is <a href="http://stackoverflow.com/questions/9635292/fluent-nhibernate-map-yesno-when-column-is-nullable">how to map string flag column to bool property</a>.

Noyabronok wrote Mar 9, 2012 at 2:23 PM

Luis_Fernando wrote Mar 9, 2012 at 8:35 PM

This is the kind of thing that this helper should be doing for you!
I've found the problem and soon we will have a solution. XD

Luis_Fernando wrote Mar 14, 2012 at 1:46 AM

I implemented two techniques that can help you like an ideal solution in this case.

The first, as I've mentioned before, is the concept of ValueResolvers that I extract from AutoMapper:

GridModelMapper.CreateMap<Foo, FooModel>()
            .MapProperty(foo => foo.EnabledFlag, model => model.Enabled)
            .WithResolver<BooleanValueResolver>();
BooleanValueResolver is a special class that inherits from IValueResolver.

And second, somewhat simpler, but equally interesting, I called BooleanSubstitutes.

GridModelMapper.CreateMap<Foo, FooModel>()
            .MapProperty(foo => foo.EnabledFlag, model => model.Enabled)
            .WithBooleanSubstitute<BooleanSubstitute>();
BooleanSubstitute is another special class that inherits from IBooleanSubstitute.

Luis_Fernando wrote Mar 14, 2012 at 1:51 AM

I did not have the time to arrange the documentation, but you can check the full implementation in the test project.

Here for ValueResolvers: http://tgh.codeplex.com/SourceControl/changeset/view/65bf708a1f04#Tests%2fFeatureRequests%2fBooleanToFlagResolverTests.cs

And here for BooleanSubstitutes: http://tgh.codeplex.com/SourceControl/changeset/view/65bf708a1f04#Tests%2fFeatureRequests%2fBooleanSubstitueTests.cs

I hope you enjoy.

Noyabronok wrote Mar 16, 2012 at 5:29 PM

I tested the regular and global resolvers and both work as expected. I did not test other resolvers or boolean substitute.