Saturday, April 30, 2011

NHibernate – The Good, the Bad, and the Ugly, that it gets!

A data access layer usually consumes 30% of the development time. A reasonable ORM can save you 90% of that 30% time. One such big hit is NHibernate.
Steps to use NHibernate:
  • Decide - Model first, Database first, or Code first
  • Create Mapping
  • Configuration
  • Query!

Pros:
  • Caching
  • Detached object
  • Concurrency
  • Interceptors
  • Batch processing
  • Attributes
  • Fluent Syntax
  • Database independency
  • Pretty mature, and large community
  • Open source
  • Model classes are POCO
Cons:
  • No visual modeler
  • Alot of mapping code that requires to be put into
  • Classes must have a no-arg constructor
  • Classes should have a  private Long id;
  • Classes may have private database attributes
  • Clumsy mapping/configuration files
Note that, to handle mappings/configurations, Fluent NHibernate is there. Fluent NHibernate is not a replacement for NHibernate or LINQ but merely a helper library that helps you configure NHibernate in code rather than using XML files; Fluent NHibernate defines helper classes which significantly facilitate the task of providing the correct configuration.
  • No good LINQ to NHB! still under development – very, very young!
  • Stored procedures in NHB; challenging.
  • Increased startup time due to metadata preparation ( not good for desktop like apps)
  • Huge learning curve, especially for those having no ORM background.
  • Pretty challenging to fine-tune the generated sql. For instance, see following SQL:
  •    1: SELECT    this_.[CHEQUE_ID] as CHEQUE1_0_1_, this_.[CHEQUE_TYPE_ID] as CHEQUE2_0_1_, this_.[BATCH_ID] as BATCH3_0_1_, this_.[ENTRY_DATETIME] as ENTRY4_0_1_, this_.[STATE_ID] as STATE5_0_1_, this_.[MICR_AMOUNT] as MICR6_0_1_, 
       2:         this_.[CHEQUE_NUMBER] as CHEQUE7_0_1_, this_.[PHEONIX_REFERENCE_NUMBER] as PHEONIX8_0_1_, this_.[ACCOUNT_NUMBER] as ACCOUNT9_0_1_,this_.[ACCOUNT_TITLE] as ACCOUNT10_0_1_, this_.[BRANCH_CODE] as BRANCH11_0_1_, this_.[ENTITY_ID] as ENTITY12_0_1_, this_.[FRONT_IMAGE] as FRONT13_0_1_, this_.[BACK_IMAGE] as BACK14_0_1_, this_.[IS_LINKED] as IS15_0_1_, this_.[CHEQUE_AMOUNT] as CHEQUE16_0_1_, 
       3:         this_.[LINKED_CHEQUE_NUMBER] as LINKED17_0_1_, this_.[LINKED_ACCOUNT_NUMBER] as LINKED18_0_1_, this_.[LINKED_CHEQUE_AMOUNT] as LINKED19_0_1_, this_.[LINKED_BENEFICIARY_ACCOUNT_NUMBER] as LINKED20_0_1_, this_.[EXCEPTION_DESCRIPTION] as EXCEPTION21_0_1_, this_.[OWNER_VERIFIER] as OWNER22_0_1_, this_.[CUSTOMER_TYPE_CODE] as CUSTOMER23_0_1_, this_.[IS_STOPPED] as IS24_0_1_, this_.[IS_OVERDRAW] as IS25_0_1_, this_.[LOCK_DATETIME] as LOCK26_0_1_, this_.[DEPOSIT_BANK] as DEPOSIT27_0_1_, this_.[AVAILABLE_BALANCE] as AVAILABLE28_0_1_, this_.[LINKED_DEPOSITED_BRANCH] as LINKED29_0_1_, this_.[LINKED_CHEQUE_NAME] as LINKED30_0_1_, b1_.[CHEQUE_ACTIVITY_ID] as CHEQUE1_1_0_
       4:         , b1_.[CHEQUE_ID] as CHEQUE2_1_0_, b1_.[ACTIVITY_TYPE_ID] as ACTIVITY3_1_0_, b1_.[Status] as Status4_1_0_, b1_.[REJECTION_REASON_ID] as REJECTION5_1_0_, b1_.[IS_OVERDRAW] as IS6_1_0_, b1_.[TRANSFER_AMOUNT] as TRANSFER7_1_0_, b1_.[Description] as Descript8_1_0_, b1_.[ACTIVITY_DATETIME] as ACTIVITY9_1_0_, b1_.[USER_ID] as USER10_1_0_, b1_.[ACCOUNT_NUMBER] as ACCOUNT11_1_0_
       5:         , b1_.[UserId] as UserId12_1_0_ FROM [CPS_CHEQUE] this_ inner join [CPS_CHEQUE_ACTIVITY] b1_ on this_.[CHEQUE_ID]=b1_.[CHEQUE_ID] 
  • Hard to get session management right if used in non-typical environments ( read non webapps )
  • Not suited for apps without a clean domain object model ( no all apps in world dont need clean domain object models) .
  • Have to jump through hoops if you have badly designed ( legacy ) db schema.
You might find this interesting to know that, NHibernate is also marketed by the term “multi-database support”; this means, you *can* move from one engine to another (from SQL Server to Oracle); but this does not mean that you can connect to both the databases at a time. For instance, query from Oracle and save into the SQL Server; for this you will have to create another set of configuration file!

ADO.NET Nhibernate
Test # Operation Time (ms) NH
1 100 Reads 000.609 000.859
2 100 Reads - 3 Joins 001.844 Couldnt apply 3 level join in HQL! ツ
3 100 Inserts 000.422 000.516
4 100 Updates 000.109 000.078
5 100 Reads - 1 Join 000.328 000.781
image
FIG1: ADO.NET vs NHibernate

Happy coding! Btw, you may also like to refer to my other articles on similar topic:

 

Tuesday, April 19, 2011

Persistent Dictionary

Key Features:
A data structure implementation similar to Dictionary in .NET.
- Writes objects to file system to preserve the memory
- Hold keys/locations in memory
- Retrieves any object by passing key in less than five milliseconds
Output, with 10000 inserts/updates/deletes:
image
Memory profiling:
image
   1: using (CPersistentDictionary lst = new CPersistentDictionary(@"C:\persist.kkhan"))
   2: {
   3:     Stopwatch timer = new Stopwatch();
   4:  
   5:     //1. Insert/update items
   6:  
   7:     int threshold = 10000;
   8:     timer.Start();
   9:     for (int i = 0; i < threshold; i++)
  10:     {
  11:         lst.Add("Counter" + i.ToString(), i.ToString());
  12:     }
  13:     timer.Stop();
  14:     Console.WriteLine("Items processed(add):{0}", threshold);
  15:     Console.WriteLine("Time elapsed in (ms):{0}  ({1} secs)", timer.ElapsedMilliseconds, TimeSpan.FromMilliseconds(timer.ElapsedMilliseconds).Seconds);
  16:  
  17:  
  18:     //2. Read items
  19:     timer.Start();
  20:     for (int i = 0; i < threshold; i++)
  21:     {
  22:         var o = lst["Counter" + i.ToString()];
  23:     }
  24:     timer.Stop();
  25:     Console.WriteLine("Items processed(read):{0}", threshold);
  26:     Console.WriteLine("Time elapsed in (ms):{0}  ({1} secs)", timer.ElapsedMilliseconds, TimeSpan.FromMilliseconds(timer.ElapsedMilliseconds).Seconds);
  27:  
  28:  
  29:     //3. Remove items
  30:     timer.Start();
  31:     for (int i = 0; i < threshold; i++)
  32:     {
  33:         lst.Remove("Counter" + i.ToString());
  34:     }
  35:     timer.Stop();
  36:     Console.WriteLine("Items processed(Remove):{0}", threshold);
  37:     Console.WriteLine("Time elapsed in (ms):{0}  ({1} secs)", timer.ElapsedMilliseconds, TimeSpan.FromMilliseconds(timer.ElapsedMilliseconds).Seconds);
  38:  
  39:  
  40:  
  41:     Console.ReadKey();
  42: }

 http://persistentdictionary.codeplex.com

Monday, April 18, 2011

CREATE TABLE FROM SELECT STAR

This answers the questions:
  • How to create a new table(on the fly) out of a query result?
  • How to copy schema into a new table out of a query result?
SQL Server:


   1: SELECT * INTO NEW_TABLE 
   2:  FROM SOURCE_TABLE 

mySQL:


   1: CREATE TABLE NEW_TABLE 
   2:  SELECT * FROM SOURCE_TABLE; 

Oracle:

   1: SELECT * INTO NEW_TABLE
   2:  FROM SOURCE_TABLE 

or

   1: SELECT Col1, Col2, Col_n INTO NEW_TABLE
   2:  FROM SOURCE_TABLE 

Postgre SQL:

   1: CREATE TABLE NEW_TABLE
   2:  AS SELECT * FROM SOURCE_TABLE;

Note, you can always use WHERE 1=0  if you want to copy only schema.

exploits_of_a_mom

Enjoy!

Sunday, April 10, 2011

Covariance and Contravariance

Covariance is when an object that is instantiated with a more derived type is assigned to an object that is instantiated with a less derived type.
For instance,
   1: IEnumerable<string> strings = new List<string>(); 

The assignment compatibility is preserved. Know that:

Invariant means, must use the exact type – be ‘in’ or ‘out’

Covariant means, parameter type can be of a derived class type; upcast’able; more specific to more general. Specified as output types: return types, 'out' params, get properties. Array types fall in this category.

Contravariant is opposite of covariance. Parameter type can be a parent class type; downcast'able; more general to specific type. Use base type where a child type was expected. Specified as input types: set, 'in' parameters, etc.

Covariance and contravariance (or simply “variance”) are advanced concepts. The motivation behind introducing and enhancing variance in C# was to allow generic interface and generic types (in particular, those defined in the Framework, such as IEnumerable<T>() to work more as we would expect.

Conventionally, array types are covariant. This means that X can be cast to Y if X subclasses Y. For instance:


   1: Bear[] bears = new Bear[3];
   2: Animal[] animals = bears; // OK

The downside of this reusability is that element assignments can fail at runtime:


   1: animals[0] = new Camel(); // Runtime error. Why, because Animal class is 
   2: //expecting Bears, notCamels!

Covariance (and contra variance) in interfaces is something that you typically consume: it’s less common that you need to write variant interfaces.

See following example:


   1: //Base type
   2: class Car { public string name = "Base car"; } 
   3:  
   4: //Sub type
   5: class Honda : Car { public Honda() { name = "Specific car: 
   6: Honda"; } } 
   7:  
   8: class Program
   9: {
  10:  delegate T Func<out T>(); /*Covariant; remember? Specified as 'out'put types*/
  11:  
  12: delegate void Action<in T>(T a);/*Contravariant; Specified as 'in'put types!*/
  13:  static void Main(string[] 
  14: args)
  15:  {
  16:  // Example: Covariance
  17:  Func<Honda> child1 = () => new Honda();
  18:  Func<Car> parent1 = child1; //Assignment compatibility is preserved 
  19:  
  20:  // Example: Contravariance
  21:  Action<Car> parent2 = (someArgs) => { Console.WriteLine(someArgs.name); };
  22:  Action<Honda> child2 = parent2;//Assignment compatibility is maintained 
  23:  child2(new Honda());//Prints, Specific car: Honda 
  24:  
  25: Console.ReadKey();
  26:  }
  27: }

The type system is free to allow us to safely upcast and downcast between those interfaces in the direction indicated by the keyword. You might like exploring more here.
It's really not a "save the day" sort of feature. It's more of a "it works the way I expect it to" feature - Eric Lippert
Enjoy, variants in life! (0:

Thursday, April 7, 2011

Will I ever be able run windows phone 7 on windows xp machine?

This post answers the following questions:
  • How to run Windows Phone Development Tools on Windows XP?
  • How to run install windows phone developer resources on windows xp?
  • XDELauncher.EXE vs XDE.exe?
I tried running windows phone 7 development environment from an xp machine. Amazing! the windows phone 7 developer phone would not install on xp machine, in the first place.

When you download a windows phone 7 online installation executable (vm_web.exe) and double click the file, it throws an error saying that a better OS is required, which means a Windows 7 or Vista.

Dint work!

Then I thought that I should download the .ISO (WPDT_RTM_en1.iso); and may be I get lucky to find the exact files that required installation.

This helped digging in more, and was able to find in the extracted files, a folder named WindowsPhone inside WCU folder. Installed XNA Game Studio, and Expression Blend without a glitch. What did not work was WindowsPhoneDeveloperResources_en.msi; it did not install. Same error, a better OS is required.

I was able to see the windows phone templates in visual studio 2010 professional; that kept on throwing the error that it requires windows phone developer resources!

Dint work!

Some how I still was sure that I'd be able to run the windows phone 7 application on a windows xp machine.

I tried installing Visual Studio 2010 Ultimate; and bang! it did the trick (0:

But wait!

I get this compilation error which says, Device Emulator is not detected. Install the Device Emulator.

Woohoo!!!

And this happiness turned in to a nightmare when I tried lauching the WP7 emulator (XDELauncher.exe, found in \Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools\XDE Launcher); and un/fortunately, it did not run. I click on it, it seems that it runs, but it does not. When you click on the file, the program ends, it seems, before it starts!

Dint work!

I still, "had" some hope... so I asked my friend google; but to my surprise it responded me with zero result set.


Ah ha! (made me scratch my skull)

It turned out not many people know about the XDELauncher.exe. And it seems that in Windows 7, XDELauncher.exe is called XDE.exe.

Here, another one like myself tried a different method of installation which "did" work! But, not really worked! (0:

The emulator requires:
  • DirectX 10
  • WDDM Driver

Both of which do not exists on Windows XP. Installing DirectX 10 also did not work.

Dint work!

This issue was raised on Microsoft Connect on May/4/2010; currently in "Review" status, with only 1 vote for it! Sounds like windows xp is scrap already. What will those do whos "corporate standard" is still Windows XP.

From another, more into "mobile-dev" says:
"I work for a large mobile silicon vendor with many, many developers working on WP7. Our corporate standard is Windows XP, and I can promise you that a bunch of very bright people have spent a lot of time trying to get this to work."

It seems, even if you are able to install and run the WP7 app successfully, you cannot guarantee that it will run smoothly everywhere. The hacked/cracked environment  that you will setup will be full of surprises. (0:

Btw, if you "still" want a workaround while staying on XP - get a VM! I created a virtual (VMWare) environment with windows 7, visual studio 2010 ultimate, and windows phone 7 developer tools - Just need to see if it works!

I'll post an update as soon as I deploy my first app on Windows Phone 7 App Store.

Update 2011/APR/21: (for those who are interested)

"Running Windows Phone developer edition in Virtual Machine is not supported". Yep, damn!

From MSDN Forums:
"Running Windows Phone developer edition in Virtual Machine is not supported. Windows Phone Developer Edition is supported on physical machine"
Emulator during its boot checks whether HW virtualiztion is enabled or not. If enabled and is available, it will enable it for its VM. My guess is that the VMWare VM driver must be tripping when the query is invoked. I will follow up with development team for possible solutions to fix this. For the current drop, please do not have active VM when launching the Emulator.

You might also enjoy this discussion.


Enjoy!

Wednesday, April 6, 2011

DOS Move command doesn't work on Windows 2003 Server?

MOVE command doesnt work in Windows 2003 Server; workaround?

To emulate the process, we can create a batch file and:
  • Copy the file to new folder
  • Verify the copied file
  • Delete the file from old folder

@echo off

echo -----------------------------------------
ECHO File Move Utility for Windows 2003 Server
echo -----------------------------------------

set /p loc1= Copy From location 1: 
set /p loc2= Copy To location 2: 

@echo Copying...
copy /b "%loc1%" "%loc2%"

@echo Validating...
fc /b "%loc2%"  "%loc1%" |find /i "Ditto" > nul

@echo Cleaning...
if not errorlevel 1 del /f "%loc1%"

@echo Logging...
if not errorlevel 1 >>"file.log" echo File copied successfully
if errorlevel 1 >>"file.log" echo Error removing file from "%loc1%"

@echo Complete.

A couple of gotchas to keep an eye on:
  • You could have used the MOVE.EXE command if its available on your OS; move simply alters the folder information, which means it does not move the data. While COPY.EXE may do.
  • When you compare the file, it most probably compares the contents with disk cache. In order to test, you can copy the file on a flash drive, a pause for a while, pull out the flash drive, and then compare. If it does not look for the flash drive, this means the OS uses the cached version instead.
  • Copy does not copy files that are 0 bytes long. Use XCOPY.exe to copy these files.

Related Posts

Popular Posts