Chorn Sokun's Weblog

Conquer inner fear, push it to the limit!

Archive for the ‘Castle.ActiveRecord’ Category

Convert IList to List<T>

with 7 comments

Follow up with my NHibernate Series today I have another post talking about one of my favorite Util’s method.

This come from my heavy use of NHibernate classes such as DetachedCriteria, IMultiCriteria and I love to call on it .SetResultTransformer method to transform result into strong type; however its .List() method return an IList which doesn’t uncomforted me much because I addicted to generic & strong type object.

public static IList<T> ConvertToListOf<T>(IList iList)
{
  IList<T> result = new List<T>();
  foreach (T value in iList)
    result.Add(value);

  return result;
}

With this little method it allow me to work with generic type again and that is sweet ;)

EDIT: hmm, I just discovered something interesting actually I don’t really need this at all I can just manipulate iList element through foreach().

namespace ConsoleApplication1
{
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;

  internal class Program
  {
    private static void Main(string[] args)
    {
      IList x = new ArrayList();

      for(int i = 0; i < 100000; i++)
      {
        x.Add(new Person("First #" + i, "Last #" + i));
      }

      Stopwatch watch1 = new Stopwatch();
      watch1.Start();
      foreach(Person person in x)
      {
        Console.Write(person.FirstName);
        Console.Write(person.LastName);
      }
      watch1.Stop();

      Stopwatch watch2 = new Stopwatch();
      watch2.Start();
      IList<Person> persons = ConvertToListOf<Person>(x);
      foreach(Person person in persons)
      {
        Console.Write(person.FirstName);
        Console.Write(person.LastName);
      }
      watch2.Stop();

      Console.Clear();

      Console.WriteLine("Watch #1: {0}\r\nWatch #2: {1}", watch1.Elapsed, watch2.Elapsed);
      Console.Read();
    }

    public static IList<T> ConvertToListOf<T>(IList iList)
    {
      IList<T> result = new List<T>();
      foreach(T value in iList)
      {
        result.Add(value);
      }

      return result;
    }
  }

  public class Person
  {
    public string FirstName;
    public string LastName;

    public Person(string firstName, string lastName)
    {
      FirstName = firstName;
      LastName = lastName;
    }
  }
}

However it come down to an interesting measurement issue
* Pass through *
Watch #1: 00:00:00.0075761
Watch #2: 00:00:00.0131754

* Pass through & read field *
Watch #1: 00:00:06.2585406 (process direct)
Watch #2: 00:00:06.3542894 (convert first)

Advertisements

Written by Chorn Sokun

May 27, 2008 at 10:47 am

Many to many lazzziii

leave a comment »

I scratched my head for a few hours reading between the line of the following code

DetachedCriteria filter = DetachedCriteria.For(typeof(Project))
  .Add(Expression.Eq("ID", pid))
  .SetProjection(Projections.Property("Type"));

DetachedCriteria q = DetachedCriteria.For(typeof(List_Output), "op")
  .CreateCriteria("ProjectTypes")
  .Add(Subqueries.Exists(filter));

ISession s = holder.CreateSession(typeof(List_Output));
IList result;

try{
  result = q.GetExecutableCriteria(s).List();
}finally{
  holder.ReleaseSession(s);
}

Wonder why It generate so many sql call to the server? the domain objects in discussion are Project which belong to a Type and base on selected Type a project can choices a bunch of Outputs.
So Project is belong to a Type [One-to-Many], and Type has many Outputs where Output belong to Many Types [Many-to-Many].

After a while I found the issue and got it fixed “it is the Lazzzzzzzziiiiiiiiiiiiiiiines” configuration :))
I forgot to tell Type to load Outputs in a Lazy mode and vise versa, once configured I got only one YEAH ! I mean ONE (a single) sql call to the server instead of 2 + N (where N is number of relevant Outputs in a Type)

Thanks to DetachedCriteria & the Laziness until next time don’t forget the magic word is “Lazy = true”

Written by Chorn Sokun

April 23, 2008 at 3:22 pm

Woh Woh storedprocedure no more …

leave a comment »

Read the title and want to know how to do that? come with me hacking the Castle code base or to be accurate hack NHibernate code base, what you need to bring along? not much but a SubVersion, NAnt, MbUnit and NUnit that sound enough ;)

Enjoy plug & play your database and let the Jedi rise
Happy Friday everyone !

Written by Chorn Sokun

April 18, 2008 at 3:48 pm

Let do Projection

leave a comment »

This would be a continue part from my previous post, what I tried to do is find out how to use ActiveRecord “NHiberate to be accurate” in my reporting scenario (not a CRUD) after a quick search, It came up with a few blog posts

It will take another post for me to wrap up how I come up with …. stay tune.

Edit: I shouldn’t have missed, exploring test case
Castle.ActiveRecord.Tests\ActiveRecordGenericsTestCase.cs

Written by Chorn Sokun

January 17, 2008 at 3:55 pm

IList you got me?

with 2 comments

As much as I hate to deal with numerical index I had to cross it one way or the other so be it.
Here is the fact, I am enjoy using Castle.ActiveRecord to wrap my DAL code cuz it simplify thing a lot for me > 80% somehow when it came to not so complex scenario like this one:

I want to allow my customer to list all the products and set the qty they want to order.
If they already order I would like to give them a chance to update qty for the product that they miss in the previous hit.

public IList LoadProductOrderList(int customer_id)
{
  IList result;

  ISession session = holder.CreateSession(typeof(AnnualTarget));
  try
  {
    // note: code wrapped for view
    string sql =  @"SELECT p.pid, p.name, o.qty, o.id as order_id
        FROM Products p JOIN Orders o
        ON p.pid = o.product_id  WHERE o.customer_id = :c1
        UNION
        SELCT pid, name, 0 as qty, 0 order_id FROM Products";

    result = session.CreateSQLQuery(sql)
        .AddScalar("ID", NHibernateUtil.Int32)
        .AddScalar("NAME", NHibernateUtil.String)
        .AddScalar("QTY", NHibernateUtil.Int32)
        .AddScalar("ORDER_ID", NHibernateUtil.Int32)
        .SetInt32("c1", customer_id)
        .List();

    } catch (Exception ex) {
        ....
    } finally {
        sh.ReleaseSession(session);
    }
    return result; // this is an IList ?!!! I don't like to work with it
}

As much as I hate, it is a bad idea to pass IList back to the caller object. What is interesting about this code session.CreateSQLQuery(sql) you can tell it to map the result to an Entity by call like this

session.CreateSQLQuery(sql)
    .AddEntity(typeof(EntityObjectOfTypeActiveRecord))
.List();

But anyway I have got time to dig what AddEntity would do with the object pass in to me the road a head is a bit dark. Can I have something more simple?

The simple should be:

public IList LoadProductOrderList(int customer_id)
{
    IList betterResult = new List();
    .....
    for(int i = 0; i

Now it much better to work with

Written by Chorn Sokun

December 5, 2007 at 3:40 pm

Posted in Castle.ActiveRecord

Tagged with

Once upon a time there was a ^GENERIC^

leave a comment »

Man ! how many times did you hear me say “I’m love the Generic so MUCH”. Not only it elegant but it really got it gold purpose of code reduction. Let look back at my previous solution on ActiveRecord Type Hierarchy and see how generic could help me:

[ActiveRecord("List_Lookups", DiscriminatorColumn = "Type", 
  DiscriminatorType = "String", DiscriminatorValue = "NA")]
public class Lookup: ActiveRecordBase where T: class{.... some code ...}

and now for derived class DeleteAll(), FindAll() etc are just ready to be use isn’t that cool?

[ActiveRecord(DiscriminatorValue = "PTL")]
public class ProjectTypeList: Lookup{.. zero code ;)}

Now I am ready to focus on another matter ;)

By the way x1r0k3wl’s comment come to rescue.

Written by Chorn Sokun

November 2, 2007 at 10:45 am

Table Lookup & ActiveRecord Type Hierarchy

with 2 comments

In any database application I can say. We need to have a read-only list for user to pick instead of manually key in. I knew that this can be done easily using Castle.ActiveRecord so I started out like this:

Design a lookup table

“Lookup” Table Schema:

  • ID – int primary key
  • Name – varchar(50)
  • Type – Discreminator Column

Very simple.

Generate ActiveRecord classes

[ActiveRecord("List_Lookups", DiscriminatorColumn = "Type",
  DiscriminatorType = "String", DiscriminatorValue = "NA")]
public class Lookup: ActiveRecordBase{.... some code ...}

sub-class code like this

[ActiveRecord(DiscriminatorValue = "PTL")]
public class ProjectTypeList: Lookup
{
}

Testing
Lucky that I start with this: ProjectTypeList.DeleteAll();
Which cause all the records in the Lookup table deleted. WEIRD !
It suppose to delete all records in Lookup table with column Type = “PTL”

Okay, I keep testing with FindAll() method and the result was not satisfied. I start lookup for the solution in the forum finally I got the answer from Hammett’s replied.

The answer is: “Implement our own DeleteAll(), FindAll() and other method by in the derived classes.”

using Castle.ActiveRecord;

namespace PID.Net.Models{
  [ActiveRecord(DiscriminatorValue = "PTL")]
  public class ProjectTypeList: Lookup
  {     

    public new static void DeleteAll()
    {
         DeleteAll( typeof(ProjectTypeList) );
    }     

    public new static ProjectTypeList[] FindAll()
    {
         return (ProjectTypeList[]) FindAll( typeof(ProjectTypeList) );
     }

 }
}

I hope I won’t waste my time next time I tried to deal with this scenario.

Written by Chorn Sokun

November 1, 2007 at 4:21 pm