Saturday, November 20, 2010

Tiny and beautiful universe in our head



One synapse, by itself, is more like a microprocessor--with both memory-storage and information-processing elements--than a mere on/off switch. In fact, one synapse may contain on the order of 1,000 molecular-scale switches. A single human brain has more switches than all the computers and routers and Internet connections on Earth.

Stephen J Smith

Read more here and here.

Friday, November 12, 2010

Android-Powered Lego Robot Solves Rubik's Cube in 12.5 Seconds



Android-Powered Lego Robot Solves Rubik's Cube in 12.5 Seconds. Read here!

Thursday, November 4, 2010

Microsoft: Our strategy with Silverlight has shifted

Could it bee that Microsoft is moving it's focus from Silverlight to HTML5? Read more...

Wednesday, November 3, 2010

Is your money that good?

Let me ask you one question
Is your money that good
Will it buy you forgiveness
Do you think that it could
I think you will find
When your death takes its toll
All the money you made
Will never buy back your soul


"Masters Of War" by Bob Dylan

Tuesday, November 2, 2010

Small NHibernate example with one-to-one mapping

So we have here database schema. The following database basiclly consists of two tables: my_user and user_profile respectively.
I decided to put small example were I'll demonstrate how to use one-to-one mapping in NHibernate ORM.
We will start by creating two tables. Here it is script for this:
CREATE TABLE [dbo].[my_user](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [user_name] [nvarchar](128) NOT NULL,
 [unique_id] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED 
(
 [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[user_profile](
 [user_id] [int] NOT NULL,
 [is_vip] [bit] NULL,
 [unique_id] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_Profiles] PRIMARY KEY CLUSTERED 
(
 [user_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
Now will create new console program project in Microsoft VisualStudio. Structure of project should be like in the picture above.
Pay attention to references. You should download NHibernate ORM framework from here. In time then I was writing this post I used NHibernate-2.1.2.GA-bin.zip version. Now we will create two classes which will represents our domain objects.
MyUser.cs file:
using System;

namespace NHOneToOneMapping
{
    public class MyUser
    {
        private Guid _uniqueID = Guid.Empty;
        private int _id = 0;
        private string _userName = null;
        private UserProfile _userProfile = null;
        private int _hashCode = 0;

        public MyUser()
        {
            UniqueID = Guid.NewGuid();
        }
        public Guid UniqueID
        {
            get { return _uniqueID; }
            internal set { _uniqueID = value; }
        }

        public int Id
        {
            get { return _id; }
            internal set { _id = value; }
        }

        public string UserName
        {
            get { return _userName; }
            set { _userName = value; }
        }

        public UserProfile UserProfile
        {
            get { return _userProfile; }
            set { _userProfile = value; }
        }
        
        protected virtual bool OnEquals(object other)
        {
            MyUser obj = other as MyUser;
            if (obj != null)
            {
                if (UniqueID != obj.UniqueID)
                    return false;

                return true;
            }

            return false;
        }

        public override int GetHashCode()
        {
            if (_hashCode == 0)
                _hashCode = _uniqueID.GetHashCode();

            return _hashCode;
        }

        public override bool Equals(object obj)
        {
            if (Object.ReferenceEquals(this, obj))
                return true;

            if (obj == null || !(obj is MyUser))
                return false;

            return OnEquals(obj);
        }

        public static bool operator ==(MyUser a, MyUser b)
        {
            if (Object.ReferenceEquals(a, b))
                return true;

            if ((object)a == null || (object)b == null)
                return false;

            return a.OnEquals(b);
        }

        public static bool operator !=(MyUser a, MyUser b)
        {
            return !(a == b);
        }
    }
}
UserProfile.cs file:
sing System;

namespace NHOneToOneMapping
{
    public class UserProfile
    {
        private Guid _uniqueID = Guid.Empty;
        private int _userId = 0;
        private bool _isVip = false;
        private MyUser _myUser = null;
        private int _hashCode = 0;

        public UserProfile()
        {
            UniqueID = Guid.NewGuid();
        }
        public Guid UniqueID
        {
            get { return _uniqueID; }
            internal set { _uniqueID = value; }
        }

        public int UserId
        {
            get { return _userId; }
            internal set { _userId = value; }
        }

        public bool IsVip
        {
            get { return _isVip; }
            set { _isVip = value; }
        }

        public MyUser MyUser
        {
            get { return _myUser; }
            set { _myUser = value; }
        }
        
        protected virtual bool OnEquals(object other)
        {
            UserProfile obj = other as UserProfile;
            if (obj != null)
            {
                if (UniqueID != obj.UniqueID)
                    return false;

                return true;
            }

            return false;
        }

        public override int GetHashCode()
        {
            if (_hashCode == 0)
                _hashCode = _uniqueID.GetHashCode();

            return _hashCode;
        }

        public override bool Equals(object obj)
        {
            if (Object.ReferenceEquals(this, obj))
                return true;

            if (obj == null || !(obj is UserProfile))
                return false;

            return OnEquals(obj);
        }

        public static bool operator ==(UserProfile a, UserProfile b)
        {
            if (Object.ReferenceEquals(a, b))
                return true;

            if ((object)a == null || (object)b == null)
                return false;

            return a.OnEquals(b);
        }

        public static bool operator !=(UserProfile a, UserProfile b)
        {
            return !(a == b);
        }
    }
}
We will create NHibernate xml mapping files.
MyUser.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class
  name="NHOneToOneMapping.MyUser, NHOneToOneMapping"
  table="my_user"
  lazy="false"
 >
    <id name="Id" access="field.camelcase-underscore" column="id">
      <generator class="identity" />
    </id>
    <property
      name="UniqueID"
      type="Guid"
      access="field.camelcase-underscore"
      column="unique_id"
      not-null="true"
  />
    <property
   name="UserName"
   type="String"
   access="field.camelcase-underscore"
   column="user_name"
   not-null="true"
  />
     <one-to-one
   name="UserProfile"
      class="NHOneToOneMapping.UserProfile, NHOneToOneMapping"
      cascade="all"
  />
  </class>
</hibernate-mapping>
UserProfile.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class
  name="NHOneToOneMapping.UserProfile, NHOneToOneMapping"
  table="user_profile"
  lazy="false"
 >
    <id name="UserId" access="field.camelcase-underscore" column="user_id">
      <generator class="foreign">
        <param name="property">MyUser</param>
      </generator>
    </id>

    <property
      name="UniqueID"
      type="Guid"
      access="field.camelcase-underscore"
      column="unique_id"
      not-null="true"
  />
    <property
      name="IsVip"
      type="Boolean"
      access="field.camelcase-underscore"
      column="is_vip"
      not-null="false"
  />
    <one-to-one
      name="MyUser"
      class="NHOneToOneMapping.MyUser, NHOneToOneMapping"
      constrained="true"
      foreign-key="none"
    />
  </class>
</hibernate-mapping>
No go and create SessionManager.cs file in Infrastructure folder.
using System;

using NHibernate;
using NHibernate.Cfg;

namespace NHOneToOneMapping
{
    public sealed class SessionManager
    {
        private readonly ISessionFactory _sessionFactory;

        public static ISessionFactory SessionFactory
        {
            get { return Instance._sessionFactory; }
        }

        private ISessionFactory GetSessionFactory()
        {
            return _sessionFactory;
        }

        public static SessionManager Instance
        {
            get { return NestedSessionManager.sessionManager; }
        }

        public static ISession OpenSession()
        {
            return Instance.GetSessionFactory().OpenSession();
        }

        private SessionManager()
        {
            if (_sessionFactory == null)
            {
                Configuration cfg = new Configuration().Configure();
                _sessionFactory = cfg.BuildSessionFactory();

                if (_sessionFactory == null)
                    throw new InvalidOperationException("Failed to create session factory.");
            }
        }

        internal class NestedSessionManager
        {
            internal static readonly SessionManager sessionManager = new SessionManager();
        }
    }
}
You will also need configuration file “App.config” and NHibernate configuration section in it.
<?xml version="1.0"?>
<configuration>
  <configSections>
    <!-- custom sections -->
    <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
  </configSections>

  <!-- NHibernate section -->
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory name="HelloNHibernate">
      <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
      <property name="connection.connection_string">
        Data Source=127.0.0.1;Initial Catalog=HelloNHibernate;Integrated Security=True;Pooling=True
      </property>
      <property name="show_sql">true</property>
      <property name="adonet.batch_size">10</property>
      <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
      <property name="use_outer_join">false</property>
      <property name="command_timeout">60</property>
      <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
      <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
      <property name="current_session_context_class">NHibernate.Context.ThreadStaticSessionContext, NHibernate</property>
      
      <property name="generate_statistics">true</property>
      <!-- add mapping assemblies -->
      <mapping assembly="NHOneToOneMapping"/>
      
    </session-factory>
  </hibernate-configuration>
  <!-- END NHibernate section -->

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
And the final peace program itself.
Program.cs
using System;
using System.Collections.Generic;

using NHibernate;
using NHibernate.Context;

namespace NHOneToOneMapping
{
    class Program
    {
        static void Main(string[] args)
        { 
            ISession session = SessionManager.SessionFactory.OpenSession();
            CallSessionContext.Bind(session);

            session.Transaction.Begin();

            IList users = session.CreateCriteria().List();
            foreach (MyUser u in users)
            {
                Console.WriteLine("id: " + u.Id +
                    "| UserName: " + u.UserName +
                    "| Profile.IsVip: " + u.UserProfile.IsVip);
            }

            UserProfile profile = new UserProfile();
            profile.IsVip = true;

            MyUser user = new MyUser();
            user.UserName = "Jhon";
            user.UserProfile = profile;
            user.UserProfile.MyUser = user;

            session.Save(user);

            users = session.CreateCriteria().List();
            foreach (MyUser u in users)
            {
                Console.WriteLine("id: " + u.Id +
                    "| UserName: " + u.UserName +
                    "| Profile.IsVip: " + u.UserProfile.IsVip);
            }

            session.Delete(user);

            users = session.CreateCriteria().List();
            foreach (MyUser u in users)
            {
                Console.WriteLine("id: " + u.Id +
                    "| UserName: " + u.UserName +
                    "| Profile.IsVip: " + u.UserProfile.IsVip);
            }

            session.Transaction.Commit();

            Console.ReadLine();

            session = CallSessionContext.Unbind(SessionManager.SessionFactory);
            if (session != null)
            {
                if (session.Transaction != null && session.Transaction.IsActive)
                    session.Transaction.Rollback();
                else
                    session.Flush();

                session.Close();
            }

            session.Dispose();
        }
    }
}
Now run it!
First results. As you can see we query for MyUser but also get UserProfile.
id: 3| UserName: Bond  | Profile.IsVip: True
id: 4| UserName: Joe  | Profile.IsVip: False
id: 5| UserName: Supermen | Profile.IsVip: True
Here is results after we added Jhon.
id: 3| UserName: Bond  | Profile.IsVip: True
id: 4| UserName: Joe  | Profile.IsVip: False
id: 5| UserName: Supermen | Profile.IsVip: True
id: 8| UserName: Jhon  | Profile.IsVip: True
And here are results after we removed Jhon.
id: 3| UserName: Bond  | Profile.IsVip: True
id: 4| UserName: Joe  | Profile.IsVip: False
id: 5| UserName: Supermen | Profile.IsVip: True
P.S. You can extract common things from MyUser and UserProfile classes and move those to new DomainObject base class. I left this intentionally as exercise for reader :)
My NHibernate session creation and binding code is for testing only, please don't use it in production code. Read about this here.
Good reading for one-to-one mapping is here.

Thank you for reading. If you have any idea you like to share or discus, leave it in comments.