Tuesday, August 18, 2015

NHibernate: Collection is always dirty

A collection that loaded from database is always dirty, that because there's a problem in mapping file. 

For example: In class A has a property named Kind with data type is an enum short. In the mapping file, this property should be mapped without specify a data type such as
        <property name="Kind" not-null="true"/>


If in the mapping file you specify a data type
        <property name="Kind" type="short" not-null="true" />


What will happen?

Problem:
When NHibernate compares your collection, this property will be conflict between short and your enum, eg: in database column Kind has value is 0, and the enum mapped to this Kind is N/A=0. At comparison time, NHibernate will treat it like a dirty data when checking it and will post an update action queue for your object even that object didn't get any modification.


NHibernate: mapping many to many with a linked table

For example I have 2 tables called ClassA and ClassB. 2 classes have connection many to many in the third table called ClassAB. ClassAB is very simple has some columns such as Id, ClassA_Id, ClassB_Id.

public class ClassA
{
public virtual string Name { get; set; }
private IList<ClassB> listB;
public virtual IList<ClassB> ListB
{
get
{
if (listB == null)
listB = new List<ClassB>();
return listB;
}
set { this.listB = value; }
}


public class ClassB
{
   public virtual string Name { get; set; }
   private IList<ClassA> listA;
   public virtual IList<ClassA> ListA
   {
     get
     {
       if (listA == null)
         listA = new List<ClassA>();
       return listA;
     }
     set { this.listA = value; }
   }
}


Mapping file for Class A will be:

<class name="ClassA" mutable="true"  optimistic-lock="none" select-before-update="false" >
    <cache usage="read-write"/>
    <id name="Id" >
      <column name="Id"  not-null="true"/>
      <generator class="guid.comb" />
    </id>

    <property name="Name" type="string" not-null="true"/>
    <idbag name="ListB" lazy="true" table="ClassAB">
      <collection-id column="Id" type="Guid">
        <generator class="guid.comb" />
      </collection-id>
      <key column="ClassA_Id"/>
      <many-to-many column="ClassB_Id" class="ClassB"/>
    </idbag>
</class>

Mapping file for Class B will be same as Class A:

<class name="ClassB" mutable="true"  optimistic-lock="none" select-before-update="false" >
    <cache usage="read-write"/>
    <id name="Id" >
      <column name="Id"  not-null="true"/>
      <generator class="guid.comb" />
    </id>

    <property name="Name" type="string" not-null="true"/>
    <idbag name="ListA" lazy="true" table="ClassAB" >
      <collection-id column="Id" type="Guid">
        <generator class="guid.comb" />
      </collection-id>
      <key column="ClassB_Id"/>
      <many-to-many column="ClassA_Id" class="ClassA"/>
    </idbag>
  </class>



Insert a new ClassB and add a link to ClassA by inserting a record to the linked table

using (var trans = new Transaction())
{

var b = new ClassB();
b.Name = "class b";
SaveOrUpdate(b);
a.ListB.Add(b);
SaveOrUpdate(a);
trans.Commit();
}

Note: If I add an attribute inverse = true at idbag as <idbag name="ListB" lazy="true" table="ClassAB" inverse="true"> NHibernate won't insert into linked table ClassAB.

Monday, August 3, 2015

Enum-flags

Flags: allow an enum value to contain many values. An enum type with the [Flags] attribute can have multiple constant values assigned to it. And it is still possible to test for these values in switches and if-statements. This is an attribute that tells .NET to allow you to assign the enum with bitwise operators. 

Enum values. The values 0x0, 0x1, 0x2, 0x4 and so on indicate powers of two. In computer bits, powers of two contain one bit set, moving from the first bit to the final bit. You could use the decimal values, 0, 1, 2, 4, 8... instead.

Example. The [Flags] attribute on an enum allows you to assign multiple values to your enum at once. You can do this with bitwise manipulations, meaning you can store an enum with A and C set, not just A and not just C.


using System;

class Program
{
    [Flags]
    enum RenderType
    {
       None = 0x0,
       DataUri = 0x1,
       GZip = 0x2,
       ContentPage = 0x4,
       ViewPage = 0x8,
       HomePage = 0x10 // Next two values could be 0x20, 0x40
    }

    static void Main()
    {
 // 1.
 // Set the first type.
 RenderType type1 = RenderType.ContentPage;

 // 2.
 // Set the second type if the condition matches.
 if (true)
 {
     type1 |= RenderType.GZip;
 }

 // 3.
 // Check the enum flags.
 Check(type1);

 // 4.
 // Set a new enum in three statements.
 RenderType type2 = RenderType.ViewPage;
 type2 |= RenderType.DataUri;
 type2 |= RenderType.GZip;

 // 5.
 // See if the enum contains this flag.
 if ((type2 & RenderType.DataUri) == RenderType.DataUri)
 {
     Console.WriteLine("True");
 }

 // 6.
 // See if the enum contains this flag.
 if ((type2 & RenderType.ContentPage) == RenderType.ContentPage)
 {
     throw new Exception();
 }

 // 7.
 // Check the enum flags.
 Check(type2);
    }

    static void Check(RenderType type)
    {
 // Switch on the flags.
 switch (type)
 {
     case RenderType.ContentPage | RenderType.DataUri | RenderType.GZip:
  {
      Console.WriteLine("content, datauri, gzip");
      break;
  }
     case RenderType.ContentPage | RenderType.GZip: // < first match
  {
      Console.WriteLine("content, gzip");
      break;
  }
     case RenderType.ContentPage:
  {
      Console.WriteLine("content");
      break;
  }
                // < second match
     case RenderType.ViewPage | RenderType.DataUri | RenderType.GZip: 
  {
      Console.WriteLine("view, datauri, gzip");
      break;
  }
     case RenderType.ViewPage | RenderType.GZip:
  {
      Console.WriteLine("view, gzip");
      break;
  }
     case RenderType.ViewPage:
  {
      Console.WriteLine("view");
      break;
  }
     case RenderType.HomePage | RenderType.DataUri | RenderType.GZip:
  {
      Console.WriteLine("home, datauri, gzip");
      break;
  }
     case RenderType.HomePage | RenderType.GZip:
  {
      Console.WriteLine("home, gzip");
      break;
  }
     case RenderType.HomePage:
  {
      Console.WriteLine("home");
      break;
  }
 }
    }
}
Output

content, gzip
True
view, datauri, gzip
The "|" operator is used in the cases. This simply means the values are combined.

refer link: http://www.dotnetperls.com/enum-flags