Using Oracle ODP with NHibernate From a C# Class Library

7 11 2008

I’m working through a few demos today and needed to connect to an Oracle 10g database using NHibernate.  NHibernate, out of the box, has a Dialect for 10g/11g using the Oracle9Dialect; however, relies on Microsoft’s OracleClient library.  I prefer Oracle’s own ODP and, thankfully, after a few configuration settings, NHibernate complies. :)

On the library with your mappings and domain classes, be sure that the hibernate.cfg.xml is set to Build Action: “Content” and Copy to Output Directory: “Copy always” when included in a class library (so it’s available in the /bin directory for the other consuming projects).

<?xml version=1.0 encoding=utf-8 ?>

<hibernate-configuration xmlns=urn:nhibernate-configuration-2.2>

       <session-factory>

              <property name=connection.provider>

                     NHibernate.Connection.DriverConnectionProvider

              </property>

              <property name=dialect>

                     NHibernate.Dialect.Oracle9Dialect

              </property>

              <property name=connection.driver_class>

                     NHibernate.Driver.OracleDataClientDriver

              </property>

              <property name=connection.connection_string>

                     User Id=user;

                     Password=password;

                     Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=
                           (PROTOCOL=TCP)(HOST=server)(PORT=1521)))
                           (CONNECT_DATA=(SERVICE_NAME=service.site)));

                     Pooling=true;

                     Enlist=false;

                     Statement Cache Size=50;

                     Min Pool Size=10;

                     Incr Pool Size=5;

                     Decr Pool Size=2;

              </property>

              <property name=show_sql>

                     true

              </property>

              <mapping assembly=NHibernateDemo.Core/>

       </session-factory>

</hibernate-configuration>

The connection.driver_class property value of NHibernate.Driver.OracleDataClientDriver tells NHibernate to look for the ODP (thanks Tomer!).  After wards, add in Oracle.DataAcess into the references of the project.  Unfortunately, there’s one more step.

If you try to compile and run tests at this point, you’ll get an NHibernate.HibernateException:

NHibernate.HibernateException : The IDbCommand and IDbConnection implementation in the assembly 
Oracle.DataAccess could not be found. Ensure that the assembly Oracle.DataAccess is located 
in the application directory or in the Global Assembly Cache. If the assembly 
is in the GAC, use <qualifyAssembly/> element in the application configuration file to 
specify the full name of the assembly.

The qualifyAssembly key goes in the App.config/Web.config file; however, I cannot get this to work using an App.config within the library itself.  For example, you’d need this qualifyAssembly key in EVERY application (tests, etc) that called your NHibernate Oracle objects.  Not cool.

For me, I’m using v2.111.6.20 of the ODP.NET for 11g.  Since I can’t get this working inside the class library, I’ll create and place it in the App.config of my Unit test project (demos with unit tests == good, console applications == bad).

<runtime>

       <assemblyBinding xmlns=urn:schemas-microsoft-com:asm.v1>

              <qualifyAssembly partialName=Oracle.DataAccess

                     fullName=Oracle.DataAccess,

                            Version=2.111.6.20,

                           Culture=neutral,

                           PublicKeyToken=89b483f429c47342 />

       </assemblyBinding>

</runtime>

Save, compile, run tests…

Successful XUnit Tests with NHibernate and Oracle ODP

Success!





Getting Oracle.DataAccess “Working” on x64

6 11 2008

Note: Please read to the end of the article before starting—results may vary.

We recently moved one of our applications off an older server to a shiny, speedy new server. In that transition, however, the new server was loaded with 64–bit Windows Server 2003 R2.  That’s fine—run .NET in 64–bit mode and kick along—my libraries are already set to run under ‘Any CPU’.

Wrong. BadFormatExceptions from Oracle.DataAccess.

Unfortunately, even the 64–bit versions of the Oracle 11g ODP returns a x86 Oracle.DataAccess.dll.  For me, setting the project to ‘x86’ (under the CPU build type) didn’t resolve the issue—it still couldn’t load the Oracle library.  A bit of hunting turned up that the x86 version of .NET isn’t installed by default.

Cool—easy fix.

To enable 32–bit access on a 64–bit platform, a few command lines are required:

First, a quick script to enable support on the system:

cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 True

Second, actually install the 32–bit version of ASP.NET onto IIS:

%SYSTEMROOT%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -i

Finally, enable 32–bit ASP.NET inside the Web Server Extensions (IIS Management Console):

Enabling x86 .NET in IIS

Now, that works—but we have a 64–bit server downgrading everything to 32–bit.  Why can’t we find and get this crackin’ at 64–bit?  We just need a 64–bit version of Oracle.DataAccess, right? 

Right. ~~~ Like most thing, the challenge is in the details.

If you look at the GAC on a machine with ODP 64–bit installed (I’m using 11.1.0.6.21 for 11g), there isn’t a x64 image available.  To find the 64–bit edition, you need the 11g Release 1 Client (it’s release 1 today).  Unfortunately, it’s 11.1.0.6.0–-a different version. GAH.  Okay, go ahead and install!

It should install a x64 image library with the following properties:

Oracle Client 64-bit

Now, in the web.config for the application, we need to add an assembly redirection.

<dependentAssembly>

       <assemblyIdentity name=Oracle.DataAccess publicKeyToken=89b483f429c47342/>

       <bindingRedirect oldVersion=0.0.0.0-2.111.6.20 newVersion=2.111.6.0/>

</dependentAssembly>

Also, in the /bin directory of your project (or where ever your referenced libraries are), make sure that the 32–bit edition is not available so that the compiler will read from the GAC.

Start up the application and go.

Too easy, right?  Yeah, I’m afraid it is.  After all this work, performance under the 64–bit environment was atrocious.  A load test of about 1000 users (using the Visual Studio Web Test tools).

Here’s the graph (click for details—it’s big so the detail is available):

64-bit Performance Monitors <— 64–bit Output

The bouncing green line in the top graph is the JIT compiler recycling over and over while the red in the bottom is the CPU pegged… and not pegged after 1000 users, but after about 15 at :15 seconds into the run.  Ugh.  I finally cut it off at 7:15 as the system was getting unstable.

So, I removed the 64–bit calls, rolled back to calling 32–bit ODP, and ran the EXACT same load tests.

32-bit Performance <— 32–bit Output

In 32–bit mode, the CPU is running as expected (the spikes are the system generating 50–100 page PDF reports on the fly using DataDynamics ActiveReports) and we hit our full 1000+ concurrent users without any real issues or memory seepage.

As a quick test, I removed the references and the few lines that are accessing Oracle databases in the application and just used the 64–bit libraries for SQL Server 2005 and my own framework libraries—and performance screamed.  I’m pretty confident that this is within Oracle.DataAccess, but more investigation is required to nail down which objects/calls.  There may be more value of simply populating the few bits of data I’m pulling out of Oracle within our SQL environment and updating it daily—like psuedo, remove materialized views. :)

So… while it’s good to know how to get the 64–bit libraries working, I’m VERY interested in why the performance was so poor.  I haven’t tossed ANTS at it yet in 64–bit mode, though that is the next test on a 64–bit development box that I’m building up.





Changing where RDP Windows Open On The Screen

5 11 2008

Have you ever created a saved RDP session and found that it wants to open on the wrong screen or in a half-scrolling window?  It’s annoying, right?

After a random opening one in NotePad2, I realized the RDP files were simply text files of properties.  Easy enough; however, the values are absolutely painful to read through.

Here’s a snippet of the windowing properties:

screen mode id:i:1
desktopwidth:i:1024
desktopheight:i:768
session bpp:i:16
winposstr:s:0,1,400,92,2500,992

I’m assuming that the properties are in order of

name:type:value

“screen mode id” takes an “i” or integer and has a value of 1 (for windowed mode).
“winposstr” takes an “s” or string and has a value of 0,1,400,92,2500,992

“winposstr” sounds a lot like Window Position String, right?

After a bit of Googling, I found KB886187 which discusses each of the attributes; however, forwards you on to another article on MSDN regarding the WINDOWPOS (for winposstr).

Roughly, winposstr follows the following order:

0,[maximized = 0, windows = 1], [left], [top], [window width aka right], [window height aka bottom]

So, I prefer an 1152×864 window (as it fits nicely on my side 1280×1024 monitor), I’d set the desktopwidth and desktopheight to:

desktopwidth:i:1152
desktopheight:i:864

Now, my “main screen” is 1920×1200, so to get things on the right-side screen (which is 1280×1024), I need to move on the left PAST 1920.

winposstr:s:0,1,1970,10,3138,910

  • 1970 is 50 (px) from the left side of my second monitor (1920 + 50)
  • 50 (px) from the top of the screen
  • 3138 (px) is 1970 (starting position) + 1152 (width of the window) + 16 for the window padding (thanks Randy!)
  • 960 (px) is 50 (starting position) + 864 (height of the window) + 46 for horizontal padding and the title bar

Now my RDP window always opens on my second monitor—just about in the center and looks good. :)





Outlook 2007’s AutoFormat Disappeared On Server 2008

4 11 2008

I recently finished installing my new workstation at work, a shiny Dell Precision T7400, with Windows Server 2008 and my normal development software.  Still bummed that I can’t get HyperV to work with the NVidia video drivers (and not angry enough to rip out the NVidia card and toss in an ATI), but things are going well.

One snafu I noticed what in Office Outlook 2007. Hyperlinks weren’t automatically changing, bulleted lists weren’t changing, etc.  I’m honestly not sure if it’s due to Server 2008, permissions, or what have you, but after checking, AutoCorrect was disabled.

Here’s how to fix it:

1. Open up a new email message, click the Office button, and down to Editor Options.

Editor Options

2. Click the Proofing section.

3. Click the AutoCorrect Options… button.

4. Set your options on the various tabs. 

Here are a few of the more common ones that I set from the AutoCorrect and AutoCorrect As You Type tabs:

 AutoCorrect Tab

AutoCorrect As You Type

5. Click OK and Close out of the Editor Options and you’re good to go.





Technical Difficulties and PSA

4 11 2008

Wrapping up a few big projects at work and consulting; however, recent upgrades to both my home system and work have left me BlogJet-less.  Boot it up and POOF, unhandled exceptions galore.  It’s like the voting machines in Virginia today.

I’m still trying to find a way to get it working, but no joy so far and the stack of ideas and things to blog is adding up (and the WordPress web UI for posting is just painful for code).

So, hopefully I’ll find a spiffy new tool (or get BlogJet working) in the next few days…

Now, for the PSA:

GO VOTE.  Seriously.





Communicating Process Improvement Benefits

7 10 2008

Paper and PencilA large part of my job is process improvement—working with various departments and groups in our organization (K-12 education) to see where technology would provide cost savings and “better ways” of doing things.  I really do enjoy it and like to see people empowered with tools to do their job better.

We’re slowly running into a culture clash—those who are holding on desparately to the paper and those who are forcing change.  Unfortunately, those “forcing change” don’t want to force it—they want our department (or anyone else) to be the “bad guys.” 

That’s cool—I can be the bad guy.

Unfortunately, it’s difficult to sell to the individuals a different process when those at the highest levels (their bosses) can’t sell it.

Here’s an example we’re running into:

For years, thousands of staff members have used paper and pencil bubble sheets to do grading.  Paper, handwritten grade cards went home to students (NCR paper copies each grading cycle).  These copies were lost, destroyed, and unreadable by the end of the year.  In addition, the paper, labels, and copies cost into the tens of thousands per year.  It wasn’t a good situation (considering it’s 2008) for parents or teachers.

A new, online grading system was requested by leadership; throughout it’s development both the customer and the focus group of the customer’s customers (those thousands of staff members) tested, worked hand-in-hand, and approved the application, it’s layout, and performance metrics.

However, after rolling it out, the complains came rolling in.  Filling a report out takes more time than “ticking off bubbles on paper” per student.  Latency in the network, across VPN for home users, and simply using the application puts it at about 35 seconds per student (1–2 seconds to load, 30 seconds for the teacher to mark their grades using the drop downs, 2–3 seconds to save and return validation).  The server side runs well—the app runs fast, but we can’t push it down the wire any faster.  There’s latency in there that developers can’t attack—especially in web applications.

When we try to reason and explain the technology, we’re countered with “well, in 2–3 seconds, I can put 5–10 check marks on a piece of paper—that’s just wasting my time.”  And of the postive benefits of the system?  So far, they’re not to be seen—those pushing for it can’t (or won’t) stand up for it. 

At this point, should it be the developers to advocate the application if the customers (the end users are the customers of our customer) don’t want to deal with the “pressure” of implementing change?

If the qualifiers for the process improvement are met, but adoption wavers because of lack of support—who’s call is that?

Just curious what everyone out there thinks.  At this point, I’m in coaching mode with our customers to work with them on how to sell change and get buy in from their customers…

 





Testing/Profiling From the Web Server

7 10 2008

Running ANTS Profiler or gathering other information is fine and good against the local IIS on my workstation; however, sometimes it’s good to see how things perform on server-class systems.  Our development/testing servers are, in many cases, nearly identical to our production servers to provide the most accurate baselines possible. 

For the past few weeks, I’ve wanted to run performance profiling locally on the development server; however, I could never get single sign-on authentication to work.  The domain authentication box would popup, not accept the password, and throw an HTTP 401.1 denied message.

Until recently, I simply shrugged it off as something I’ve dinked with and broke on the server—and it probably needed reimaged.  A bit of Googling pointing out that, as with most things, this “behavior is by design” in Server 2003 SP1 and higher.

From KB 896861:

This issue occurs if you install Microsoft Windows XP Service Pack 2 (SP2) or Microsoft Windows Server 2003 Service Pack 1 (SP1). Windows XP SP2 and Windows Server 2003 SP1 include a loopback check security feature that is designed to help prevent reflection attacks on your computer. Therefore, authentication fails if the FQDN or the custom host header that you use does not match the local computer name.

Yep, that’s me—we use host headers for most of our sites, e.g. app1.domain.local.

The KB article lists two “work arounds”:

  • Disable the loopback check
  • Specify host names

I tried the second option first; however, I couldn’t get it to accept more than three names and didn’t like having to modify the registry (even on a development server) every time we rolled a new app to it to test.

The second option to simply disable the check did work; however, is not something I’d roll out to a non-development box (our dev servers are on a separate IP network and are pretty much hidden from everything else outside this building).
Method 1: Disable the loopback check
Follow these steps:
 
1. Click Start, click Run, type regedit, and then click OK.
2. In Registry Editor, locate and then click the following registry key:
 
 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
3. Right-click Lsa, point to New, and then click DWORD Value.
4. Type DisableLoopbackCheck, and then press ENTER.
5. Right-click DisableLoopbackCheck, and then click Modify.
6. In the Value data box, type 1, and then click OK.
7. Quit Registry Editor, and then restart your computer.
 




Handling Sessions Objects with a Custom Session Manager

18 09 2008

I try not to abuse Session objects too much—keep them simple types, not too many, etc.  However, on a recent project where there was a few of us dinking with the code, it became an issue with how the keys were named, where they were created, etc. 

To correct the problem on future projects, I tossed together a little class in the mix to manage the “keys”.

public class SessionManager

{

protected HttpSessionState session;

 

       public SessionManager(HttpSessionState httpSessionState)

       {

              session = httpSessionState;

}

 

public SessionManager()

       {

              session = HttpContext.Current.Session;

}

 

       public void Dispose()

       {

              session.Clear();

              session.Abandon();

       }

 

       public bool IsFoo

       {

              get { return

session["IsFoo"].ConvertTo<bool>(); }

set { session["IsFoo"] = value; }

}

 

       public string FooId

       {

              get { return

session["FooId"].ConvertTo<string>(); }

set { session["FooId"] = value; }

}

}

The two constructors allow the consumer to either accept the default HttpContext.Current session object or provide their own.  From there, the “keys” are coded within this page rather than in every code block throughout the site. 

To use the SessionManager:

I inherit all of my pages from a default page (DefaultPage, for lack of a better name) and place the session manager as a public field.

DefaultPage.cs:

public class DefaultPage : Page

{

public SessionManager CurrentSession;

      

protected void Page_PreInit(object sender, EventArgs e)

       {

              CurrentSession = new SessionManager();

}

}

To use the CurrentSession field, simply reference it.  This makes reading/writing to session easy on the inheriting pages.

private List<Foo> GetFooList()

{

var foo = sessionManager.IsFoo

              ? Foo.GetFooById(sessionManager.FooId)

: new List<Foo> { Foo.GetEmptyFoo() };

return foo;

}

Still tweaking to do, but it works and seems clean enough.

Suggestions or better ideas? :) 





Tweaking .NET Machine.Config For Production Deployments

17 09 2008

I recently rolled out an enterprise wide app to a pilot group (which, since pilots are silly or so I’m told, that means we rolled it out to EVERYONE or ~1200 users).  Not a huge amount by any means, but without a pilot, we didn’t have a good baseline to gauge performance settings.

I remember reading an article by Peter Bromberg ages ago about tuning IIS 6.0.  After a bit of Googling, I found it again and, one-by-one, started tweaking various settings on our development environment and hitting it with 500–1000 concurrent load users.

Here’s what I came up with that seemed to give the best bang for the buck.

  <system.net>

    <connectionManagement>
      <add address=”*” maxconnection=”100″ />
    </connectionManagement> 

  </system.net>

maxconnections – This sets how many outgoing connections the ASP.NET service can make FROM the server, such as to databases, web services, etc.  Increasing this can increase the number of concurrent connections are available to your application.

  <system.web>

    <deployment retail=”true” />

    <processModel
                autoConfig=”true”
                memoryLimit=”75″
                maxIoThreads=”100″
                minIoThreads=”30″
                minWorkerThreads=”40″
                maxWorkerThreads=”100″
                clientConnectedCheck=”00:00:05″ />

    <httpRuntime
                minFreeThreads=”352″
                minLocalRequestFreeThreads=”308″
                enableKernelOutputCache=”false”
                maxRequestLength=”10240″ />  

  </system.web>

deployment/retail – Setting retail=”true” essentially forces all web applications on that machine to compile without debug.  This is extremely helpful for those rare cases that you forget to set debug=”false” on a web project.  In a production environment, debug files should rarely/never be needed, so this blankets the server.

processModel/autoConfig – autoConfig sets everything to the defaults except what I explicitly set below.  Just at time saver.

processModel/memoryLimit – This is a percentage of how much memory a web process can consume before it splits off into another process.  Since our production servers ONLY run IIS and web servers, then it should be safe to set this to 75% of the total memory on the box.

processModel/maxIoThreads – Based on Bromberg’s recommendation, this controls how many IO threads are allowed to the web process.  minIoThreads is the other side of the scale.

processModel/maxWorkerThreads – Based on Bromberg’s recommendation, this controls how many worker threads are in the pool for each web process.  minWorkerThreads is the other side of the scale.

processModel/clientConnectedCheck – An excellent setting that tells the server to check every 5 seconds to see if the client is connected.  If not, trash their queued requests (since they’re not there to receive it anymore).  According to this source, this also helps for those situations where users get “impatient” and machine-gun click the mouse trying to get a response.

httpRuntime/minFreeThreads – Based on Bromberg’s recommendation, a setting that tells the machine what the minimum number of threads in the pool must be in order for incoming requests to be processed.

httpRuntime/minLocalRequestFreeThreads – Same as the prior, but for the local machine (localhost)—good for locally hosted web servers; however, I’m not sure if it’s smart enough to know if “localhost” and a registered DNS entry are the same (I never refer to a machine as localhost).  It’s set, but more research required here.

httpRuntime/enableKernelOutputCache – This is set to FALSE for me, though most everything recommends true.  Why?  Kernel Mode caching is great—it’s speedy and a good way to speed up pages; however, we’ve had several issues in the past (on IIS 6) where it caused sessions to “merge” across authenticated users.  The issue is described here in KB917072.  Setting this for the machine just solves the problem overall.  Honestly, unless I can guarantee a way that the sessions/cookies won’t cross, I’ll give up a few milliseconds of performance in the day to guarantee a user experience.

httpRuntime/maxRequestLength – The default request length is 4096K; however, for uploading large file into the system, that becomes the limit.  A few of our applications allows users to upload documents, PDFs, etc. and attach them—we need a larger limit.  ~10MB seems to work well.  You “could” set this in the web.config; however, we base our production server at 10MB and then ramp up from there.

As with all tweaks, your mileage may vary—as mine does every single day.  I’d be interested to hear of other tweaks for higher performing web sites as well as feedback on the above (especially if I misinterperted a setting and simply haven’t seen the failure yet).





Using xUnit.net in ReSharper 4.1 and MVC

11 09 2008

Ben Taylor has saved us all a HUGE load of frustration by releasing a patched version of the xUnit.net installer and libraries that works with ReSharper 4.1.

There’s a final step, however, if you want it to work with the MVC Framework (this is for Preview 5).

The default xUnit.net MVC template package includes a 3rdParty directory for the xUnit.dll file.  The Test project also references that same library for the context of the tests.  To take advantage of Ben’s new 4.1’esque library, you need to update the 3rdParty file with his or you’ll be seeing red.

Steps:

1. Open your MVC Test project.

2. Remove (delete) the 3rdParty/xunit.dll.

3. Add an Existing File to the 3rdParty directory, pointing to the new library from Ben.

4. Under the Test project’s References, refresh the xunit reference and be sure it’s picking up the new file (the caution icon should disappear).

5. Run your tests in ReSharper and be very happy. :)

Working MVC tests with xUnit and Ben's Patch.