The official Fatica Labs Blog! RSS 2.0
# Wednesday, 28 September 2011

This is just an example helper class to create a generic IResultTransformer that allow us to convert an NHibernate result into a string[] suitable for generating a CSV. Nothing advanced, just some basic stuff and a fluent interface syntax. Let’see the class:

class CsvTransformer<T>:IResultTransformer
    {
        List<Func<T, string>> mappers = new List<Func<T,string>>();
        Func<object,T> elemSelector = k=>(T)((object[])k)[0];
        public CsvTransformer()
        {
            
        }
        #region IResultTransformer Members

        public System.Collections.IList TransformList(System.Collections.IList collection)
        {
            List<string[]> csv = new List<string[]>();
            foreach (object elem in collection)
            {
                List<string> row = new List<string>();
                foreach (var map in mappers)
                    row.Add(map(elemSelector(elem)));
                csv.Add(row.ToArray());
            }
            return csv;
        }

        public object TransformTuple(object[] tuple, string[] aliases)
        {
            return tuple;
        }

        #endregion
        public CsvTransformer<T> Extract(Func<object, T> elemSelector)
        {
            this.elemSelector = elemSelector;
            return this;
        }
        public CsvTransformer<T> Map(Func<T, string> map)
        {
            mappers.Add(map);
            return this;
        }
    }

 

And an example usage can be:

session.QueryOver<MyEntity>()
                        .TransformUsing(newTransformers.CsvTransformer<MyEntity>()
                        .Map(k=>k.Field1)
                        .Map(k=>k.Field2)
                        .Map(k=>k.Date.HasValue?k.Date.Value.ToShortDateString():"")
                        )
                    .List<string[]>();

We can also customize how to extract data from the NHibernate returned tuple by using the .Extract method.

Easy to use and to embed as a stand alone file in our projects. What about having something similar integrating AutoMapper ?

Wednesday, 28 September 2011 15:47:56 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
NHibernate

# Tuesday, 27 September 2011

NHibernate QueryOver is a new API ( from version 3.0 )  that allow to create queries the ICriteria way, but with lambda expressions instead of raw strings. With QueryOver we have the benefit of intellisense and the code is refactoring friendly. At the moment one reference can be found on this blog post. Something not so obvious to do is a query over a portion of a date property, for instance all the entities in a certain month, and so on. Let’s have an example considering this simple entity:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  assembly="MyAssembly" namespace="MyAssembly.MyNamespace">
  <class name="Item" table="Items">
    
    <id name="Id"  type="Int64">
      <generator class="native"/>
    </id>
        
    <property type="AnsiString" name="Code" length="32"></property>
    <property type="DateTime" name="StartDate"></property>
    
  </class>
</hibernate-mapping>

And suppose we want to fetch all the entities having start date in the year 2011, with QueryOver we write:

var result = session.QueryOver<Item>()
                    .Where(
                    Restrictions.Eq(
                    Projections.SqlFunction("year"
                    , NHibernateUtil.Int32
                    , Projections.Property<Item>(item => item.StartDate)
                    ) 
                    ,2011)).List();

 

that yield the following query ( with MSSQL 2005 dialect ):

SELECT
        this_.Id as Id21_0_,
        this_.Code as Code21_0_,
        this_.StartDate as StartDate21_0_
    FROM
        Items this_
    WHERE
        datepart(year, this_.StartDate) = @p0;
    @p0 = 2011 [Type: Int32 (0)]

 

obviously we can select a projection with a portion of the date to, suppose we want to fetch the day of all item in a certain date range, we can write:

var session = NHHelper.Instance.CurrentSession;
               var result = session.QueryOver<Item>()
              .WhereRestrictionOn(k => k.StartDate).IsBetween(dlow)
              .And(dup)
              .Select(
                       Projections.SqlFunction("day"
                                   , NHibernateUtil.Int32
                                   , Projections.Property<Item>(p => p.StartDate)
                                   ))
              .List<int>();

 

obtaining the following query:

SELECT
        datepart(day,
        this_.StartDate) as y0_
    FROM
        Items this_
    WHERE
        this_.StartDate between @p0 and @p1;
    @p0 = 01/09/2011 00:00:00 [Type: DateTime (0)], @p1 = 29/09/2011 00:00:00 [Type: DateTime (0)]

 

These are really common situation when we have to fill-up gui elements, and with these tricks we can write optimal and fast queries.

Addition:

As pointed by Vahid ( Thanks a lot ! ) in the comment, with the latest version ( NH 3.2 ) things are easier since there is a shortcut for dateparts as projection extension, so the first sample became:

session.QueryOver<Item>()
                 .Where(
                    p=>p.StartDate.YearPart()==2011
                   
                    ).List();

 

and the second one:

 

session.QueryOver<Item>()
                .Where(
                   p=>p.StartDate.IsBetween(dlow).And(dup)
                   )
                   .Select(k=>k.StartDate.DayPart() )
                   .List();
surely better, and this is the way to go with newer NH versions, and producing of course the same DB queries.
Tuesday, 27 September 2011 11:48:57 (GMT Daylight Time, UTC+01:00)  #    Comments [2] - Trackback
NHibernate | QueryOver

# Friday, 09 September 2011

This post is an exercise, similar to this and this previous posts about using NHibernate  mapping by code new features present form version 3.2. The source inspiring it is an old post form Ayende, showing a non trivial requirement to map.

Here the DB model:

And the wanted object model:

So there is a lot of comments about DB refactoring needing, or on needing to have the linking entity as a visible entity in the model, but:

  • I like the idea of collapsing the linking entity.
  • I suppose that the DB is untouchable, as frequently happens.

Ayende solves the trouble by the <join/> mapping having an entity spawning two tables, so Address will be represented by joining the Table Address and PeopleAddress.

This can be done very easily in Mapping by code too, lets see how:

 

ModelMapper mapper = new ModelMapper();
            mapper.Class<Person>(m =>
                {
                    m.Id(k => k.Id,g=>g.Generator(Generators.Native));
                    m.Table("People");
                    m.Property(k => k.Name);
                    m.Bag(k => k.Addresses, t => 
                            { 
                                t.Table("PeopleAddresses");
                                t.Key(c=>c.Column("PersonId"));
                                t.Inverse(true);
                                
                            }
                         ,rel=>rel.ManyToMany(many=>many.Column("AddressId"))
                        );
                }

                );

            mapper.Class<Address>(m =>
                {
                    m.Id(k => k.Id, g => g.Generator(Generators.Native));
                    m.Table("Addresses");
                    m.Property(p => p.City);

                    m.Join("PeopleAddresses", z => 
{
z.Property(p => p.IsDefault);
z.Property(p => p.ValidFrom);
z.Property(p => p.ValidTo);
z.Key(k => k.Column("PersonId"));
});

That yield  the following mapping:

<?xml version="1.0" encoding="utf-16"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="TestMappingByCode" assembly="TestMappingByCode" xmlns="urn:nhibernate-mapping-2.2">
  <class name="Person" table="People">
    <id name="Id" type="Int32">
      <generator class="native" />
    </id>
    <property name="Name" />
    <bag name="Addresses" table="PeopleAddresses" inverse="true">
      <key column="PersonId" />
      <many-to-many class="Address" column="AddressId" />
    </bag>
  </class>
  <class name="Address" table="Addresses">
    <id name="Id" type="Int32">
      <generator class="native" />
    </id>
    <property name="City" />
    <join table="PeopleAddresses">
      <key column="PersonId" />
      <property name="IsDefault" />
      <property name="ValidFrom" />
      <property name="ValidTo" />
    </join>
  </class>
</hibernate-mapping>

 

Exactly the ones that Ayende proposed. As you can see is pretty straightforward map even a not so common situation.

Friday, 09 September 2011 11:59:53 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
NH Mapping By Code | NHibernate | ORM

# Friday, 02 September 2011

In this post we done some effort in automatically generate the mapping based on convention, but we miss a very common one: table names is usually the pluralized entity name. This is usually done by using an inflector. Thanks to Stack Overflow, I found this question about it, and choose that one, that is a single easily embeddable file. So we modify a little our AutoMapper class as below:

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"); 
                               }
                               );
           classCustomizer.Table(Inflector.Pluralize(type.Name));
        }

 

And this is all, the generated mapping will change as:

<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:x=""
sd="http://www.w3.org/2001/XMLSchema" namespace="MappingByCode" assembly="Mappin
gByCode" xmlns="urn:nhibernate-mapping-2.2">
  <class name="SimpleEntity" table="SimpleEntities">
    <id name="Id" column="cSimpleEntityId" type="Int32">
      <generator class="native" />
    </id>
    <property name="Description">
      <column name="txtSimpleEntityDescr" sql-type="AnsiString" />
    </property>
    <many-to-one name="Referred" column="cReferredId" />
  </class>

Just for better sharing, I published this “laboratory” project here.

Friday, 02 September 2011 14:42:10 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
NH Mapping By Code | NHibernate | ORM

# Thursday, 01 September 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, 01 September 2011 14:58:04 (GMT Daylight Time, UTC+01:00)  #    Comments [2] - Trackback
NHibernate | ORM | NH Mapping By Code

# Friday, 12 August 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, 12 August 2011 11:46:46 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Programmin | Recipes

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 2019
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 127
This blog visits
All Content © 2019, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano
Nike Winkels Nederland Outlet Nike Nederland Store Outlet Nike Nederland 2015 Outlet Nike Outlet Online Nike Sneakers Outlet