The official Fatica Labs Blog! RSS 2.0
# Thursday, September 01, 2011

Since version 3.2.0 NHibernate  has an embedded strategy for mapping by code, that basically comes from Fabio Maulo’s ConfORM. With some reading at this Fabio post,  this other one, and this one too, I wrote my own sample just to see what we can do.

Even if we can use mapping by code to map class by class the entire model, something more interesting can be done by writing some convention-based automatic mapper, that can help us even when we face legacy ( non code first ) databases with some (perverted) naming convention.

We have to consider first the ModelMapper class, this class in the NH mapping by code is the one responsible for driving the mapping generator. It provides a suite of events to intercept the actual generation of each elements in the mapping. By listening these event we can decorate the detail of the single element, for example the Id generator class, the SqlType, the column name, and so on. ModelMapper uses a ModelInspector to get the way we want to map each portion of the entity ( properties, many-to-one, collections ), or if we have a component, or a subclass and so on. We realize our AutoMapper class by deriving a ModelMapper and internally subscribing some events, and passing to it a custom ModelInspector ( we named it AutoModelInspector ).

Let’s start with a very basic model:

ultra simple model

Basically an entity that unidirectionally associates with a referred one. Let’s say we have these example database conventions:

  • Identifier column are named “c”+EntityName+”Id” and are autoincrement
  • Column description are named “txt”+EntityName+”Descr”
  • Column of type string have to be prefixed with “txt”
  • Column of type string have to be AnsiString ( for DDL generation of CHAR instead of NChar )
  • Foreign key column have to be called “c”+ForeignEntityName+”Id”

So let’s see how we wrote the custom model mapper:

class AutoMapper:ModelMapper
    {
        public AutoMapper()
            : base(new AutoModelInspector())
        {
            //subscribe required ebvents for this simple strategy ...
            this.BeforeMapClass += new RootClassMappingHandler(AutoMapper_BeforeMapClass);
            this.BeforeMapProperty += new PropertyMappingHandler(AutoMapper_BeforeMapProperty);
            this.BeforeMapManyToOne += new ManyToOneMappingHandler(AutoMapper_BeforeMapManyToOne);
            //...
            //other events....
        }
        
        void AutoMapper_BeforeMapManyToOne(IModelInspector modelInspector, PropertyPath member, IManyToOneMapper propertyCustomizer)
        {
            //
            // name the column for many to one as
            // "c"+foreignEntityName+"id"
            //
            var pi = member.LocalMember as PropertyInfo;
            if (null != pi)
            {
                propertyCustomizer.Column(k => k.Name("c"+pi.PropertyType.Name+"Id"));
            }
        }

        void AutoMapper_BeforeMapProperty(IModelInspector modelInspector, PropertyPath member, IPropertyMapper propertyCustomizer)
        {
            //
            // Treat description as a special case: "txt"+EntityName+"Descr"
            // but for all property of type string prefix with "txt"
            //
            if (member.LocalMember.Name == "Description")
            {
                propertyCustomizer.Column(k =>
                    {
                        k.Name("txt" + member.GetContainerEntity(modelInspector).Name + "Descr");
                        k.SqlType("AnsiString");
                    }
                    );
            }
            else
            {
                var pi = member.LocalMember as PropertyInfo;
                
                if (null != pi && pi.PropertyType == typeof(string))
                {
                    propertyCustomizer.Column(k =>
                    {
                        k.Name("txt" + member.LocalMember.Name);
                        k.SqlType("AnsiString");
                    }
                   );
                }
            }
        }
       
        void AutoMapper_BeforeMapClass(IModelInspector modelInspector, Type type, IClassAttributesMapper classCustomizer)
        {
            //
            // Create the column name as "c"+EntityName+"Id"
            //
            classCustomizer.Id(k => { k.Generator(Generators.Native); k.Column("c" + type.Name + "Id"); });
        }

        
    }

 

The event handlers apply the convention we said before. As we see we pass a special model inspector in the constructor, that is implemented as below:

class AutoModelInspector:IModelInspector
    {
        #region IModelInspector Members

       
        public IEnumerable<string> GetPropertiesSplits(Type type)
        {
            return new string[0];
        }

        public bool IsAny(System.Reflection.MemberInfo member)
        {
            return false;
        }

        
        public bool IsComponent(Type type)
        {
            return false;
        }

       
        public bool IsEntity(Type type)
        {
            return true;
        }

       
        
        public bool IsManyToOne(System.Reflection.MemberInfo member)
        {
            //property referring other entity is considered many-to-ones...
            var pi = member as PropertyInfo;
            if (null != pi)
            {
                return pi.PropertyType.FullName.IndexOf("MappingByCode") != -1;
            }
            return false;
        }

        public bool IsMemberOfComposedId(System.Reflection.MemberInfo member)
        {
            return false;
        }

        public bool IsMemberOfNaturalId(System.Reflection.MemberInfo member)
        {
            return false;
        }

      
        public bool IsPersistentId(System.Reflection.MemberInfo member)
        {
            return member.Name == "Id";
        }

        public bool IsPersistentProperty(System.Reflection.MemberInfo member)
        {
            return member.Name != "Id";
        }

        public bool IsProperty(System.Reflection.MemberInfo member)
        {
            if (member.Name != "Id") // property named id have to be mapped as keys...
            {
                var pi = member as PropertyInfo;
                if (null != pi)
                {
                    // just simple stading that if a property is an entity we have 
                    // a many-to-one relation type, so property is false
                    if (pi.PropertyType.FullName.IndexOf("MappingByCode") == -1)
                        return true;
                }

            }
            return false;
                
        }

        public bool IsRootEntity(Type type)
        {
            return type.BaseType == typeof(object);
        }

       
        
        public bool IsTablePerClassSplit(Type type, object splitGroupId, System.Reflection.MemberInfo member)
        {
            return false;
        }

       
        public bool IsVersion(System.Reflection.MemberInfo member)
        {
            return false;
        }

        #endregion
    }

 

As we say there is a bounch of IsXXXXX function, that are called for each portion of the class in order to know what to do with it. Our implementation is absolutely incomplete ( not implemented function omitted ), but it feet the simple requirement we stated. Then we can see how we actually realize the mapping:

static void Main(string[] args)
       {
           AutoMapper mapper = new AutoMapper();
          
           //this line simple rely on the fact
           //all and just the entities are exported...
           var map = mapper.CompileMappingFor(Assembly.GetExecutingAssembly().GetExportedTypes());

           //dump the mapping on the console
           XmlSerializer ser = new XmlSerializer(map.GetType());
           ser.Serialize(Console.Out, map);
       }

Simple, isn’t ?

The resulting map, as dumped on the console is:

image

That fulfill the actually simple requirements. So is just a matter of recognize the convention and the exceptions, and let’s go auto-mapping!

Thursday, September 01, 2011 2:58:04 PM (GMT Daylight Time, UTC+01:00)  #    Comments [2] - Trackback
NHibernate | ORM | NH Mapping By Code

# Friday, August 12, 2011

Sometimes happens that we need to roll over all the combinations of elements in multiple arrays. This operation is called Cartesian Product and is defined as:

Definition (Cartesian product): Let A1, ..., An be n sets.

Then the set of all ordered n-tuples <x1, ..., xn> , where xi Ai for all i, 1 i n ,

is called the Cartesian product of A1, ..., An, and is denoted by A1 ... An .

Achieving this is possible by some linq tricks, or by an helper class I propose in this post. But just for clarify let’s start from the example:

We have three array as below:

 { "JUICY", "SWEET" }
{ "GREEN", "YELLOW" }
{ "APPLE", "BANANA", "MANGO" }

we want to obtain all the possible tuples, ie:

 

image

This can be achieved by the following code ( helper class ):

public class CartesianProduct<T>
    {
        int[] lengths;
        T[][] arrays;
        public CartesianProduct(params  T[][] arrays)
        {
            lengths = arrays.Select(k => k.Length).ToArray();
            if (lengths.Any(l => l == 0))
                throw new ArgumentException("Zero lenght array unhandled.");
            this.arrays = arrays;
        }
        public IEnumerable<T[]> Get()
        {
            int[] walk = new int[arrays.Length];
            int x = 0;
            yield return walk.Select(k => arrays[x++][k]).ToArray();
            while (Next(walk))
            {
                x = 0;
                yield return walk.Select(k => arrays[x++][k]).ToArray();
            }

        }
        private bool Next(int[] walk)
        {
            int whoIncrement = 0;
            while (whoIncrement < walk.Length)
            {
                if (walk[whoIncrement] < lengths[whoIncrement] - 1)
                {
                    walk[whoIncrement]++;
                    return true;
                }
                else
                {
                    walk[whoIncrement] = 0;
                    whoIncrement++;
                }
            }
            return false;
        }
    }

 

And, just for completeness, the example application:

 

static void Main(string[] args)
        {
            var cross = new CartesianProduct<string>(
               new string[] { "JUICY", "SWEET" }
               , new string[] { "GREEN", "YELLOW" }
               , new string[] { "APPLE", "BANANA", "MANGO" }
               );

            Console.WriteLine("=========================================================");
            foreach (var item in cross.Get())
            {
                Console.WriteLine("{0}\t{1}\t{2}", item[0], item[1], item[2]);
            }
            Console.WriteLine("=========================================================");
        }
Really simple and clear to use in comparison with other linq based solution, even when arrays are unknown at design time.
Friday, August 12, 2011 11:46:46 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Programmin | Recipes

# Wednesday, August 10, 2011

Sometimes the difference between unit and integration test does not apply. Maybe because writing a mock is too complex or boring, or maybe you have an integration test already working and you want to use it as a unit test but the integration isn’t always available or it is slow and so on … A possible solution is “Parroting” the integrated part by creating automatically a mock when running the integration tests. A friend of mine, just realized such an idea: Wasp Parrots, even if at an early stage, it looks very promising.

Wednesday, August 10, 2011 10:45:40 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback


# Tuesday, August 09, 2011

Sometimes it is annoying that the TextBox in WPF needs to loose focus in order to updating the underlying value in the model. Having the application moving the focus in order to force the binding update is a bad trick, unacceptable if you are using MVVM. In such a case worked for me deriving a custom class from the textbox ( actually I did for the Fluent Ribbon textbox, but the concept is the same ) and programmatically updating the source, as below:

public class UpdatingBindingTextBox:TextBox
    {
        public UpdatingBindingTextBox()
        {
            this.TextChanged += new System.Windows.Controls.TextChangedEventHandler(UpdatingBindingTextBox_TextChanged);
        }

        void UpdatingBindingTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            BindingOperations.GetBindingExpression(this, TextBox.TextProperty).UpdateSource();
        }
    }
So this force the model to update at each character in input.

ADDITION:

By investigating a little more, I found this alternative on stack overflow. It is basically a behavior attached to the textbox that call a command in the ViewModel. Don’t know which one is better, I personally like the behavior way, but in any case I do need to update the binding manually into the view model…

Tuesday, August 09, 2011 4:16:06 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
WPF

# Thursday, July 21, 2011

If you plan to use the Caliburn Micro convention with buttons contained in a Fluent Ribbon you will notice that it does not works out of the box. This is because the default BindingScope.GetNamedElements does not dig inside the ribbon to looks for named control. The solution that worked for me is to modify the default behavior as swown below:

In the overridden Configure function:

defaultElementLookup = BindingScope.GetNamedElements;
           BindingScope.GetNamedElements = new Func<System.Windows.DependencyObject, IEnumerable<System.Windows.FrameworkElement>>(
               k =>
               {
                   List<FrameworkElement> namedElements = new List<FrameworkElement>();
                   namedElements.AddRange(defaultElementLookup(k));
                   Fluent.Ribbon ribbon = LookForRibbon(k);
                   if( null != ribbon )
                       AppendRibbonNamedItem(ribbon, namedElements);
                   return namedElements;
               }
               );

We need to define defaultElementLookup into the boot class as:

Func<DependencyObject, IEnumerable<FrameworkElement>> defaultElementLookup;
I saved the standard GetNamedElement function because I use it to look for the control the default way, and to look for the controls inside the Ribbon too.

Here the function LookForRibbon, that just dig into the visual tree to search for a ribbbon ( if any ):

private Fluent.Ribbon LookForRibbon(DependencyObject k)
        {
            Fluent.Ribbon foundRibbon = null;
            var contentControl = k as ContentControl;
            if (null != contentControl)
            {
                var child = contentControl.Content as DependencyObject;
                if( null != child )
                    return LookForRibbon(child);
            }
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(k); ++i)
            {
                var child = VisualTreeHelper.GetChild(k, i);
                foundRibbon = child as Fluent.Ribbon;
                if (null != foundRibbon)
                {
                    return foundRibbon;
                }
                else
                {
                    foundRibbon = LookForRibbon(child);
                    if (null != foundRibbon)
                        return foundRibbon;
                }
            }
            return null;
                
        }

 

As you guess, the function stops at the first found ribbon so we suppose there is just one ribbon for view ( quite reasonable )

As we have the ribbon we can look for the elements inside and append to the list with this function:

 

private void AppendRibbonNamedItem(Fluent.Ribbon ribbon, List<FrameworkElement> namedElements)
        {
            foreach (var ti in ribbon.Tabs)
            {
                foreach (var group in ti.Groups)
                {
                    namedElements.AddRange(defaultElementLookup(group));
                }
            }
        }

 

So we look inside each ribbon group and we treat these as Caliburn would do.

Thursday, July 21, 2011 2:35:52 PM (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Caliburn | WPF

# Tuesday, June 07, 2011

Sacha Barber expand his work on a very famous project presented about 4 years ago on CodeProject. It is a very interesting project about class diagram creation in WPF, mainly because is a good field for learning advanced WPF functionality. Here Sacha explain the new version, and below a screen shot:

Tuesday, June 07, 2011 8:22:55 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
WPF

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 123
This blog visits
All Content © 2014, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano