Archive

Archive for the ‘.net 3.0’ Category

Adventures with Fluent NHibernate

December 23, 2008 Comments off

Fluent NHibernate LogoOver the past few weeks, I’ve taken our existing framework library and reevaluated how we connect to our student information system (SIS) to pull information.  Almost all of our applications read from SIS for some bit of information or another; however, nothing writes to it.  Changes are only handled through the application itself as the business logic is blackboxed by the vendor.

In the old library, connectivity was a bit piecemeal.  When someone needed something, we wrote a test, wrote the implementation PL/SQL, and slugged in some objects.  It worked, was fairly quick, and provided a standardized mechanism for querying the system (avoiding EVERYONE recreating what constituted a ‘student’).

Unfortunately, maintaining the object relationships to the magic strings of PL/SQL code became tedious (at best) and a change was needed.  I’d been evaluating NHibernate for a couple of projects (to replace LINQ-to-SQL) as Entity Framework still doesn’t have sufficient Oracle ODP support out of the box (without paying for another provider).  NHibernate seemed ideal, but XML configuration files made me cringe.

After a bit of syntax searching, I stumbled upon Fluent NHibernate (FNH)—an API that generates both the configuration and XML mappings and allows a MUCH better refactoring experience.  I’m all for ReSharper friendly!

As you may have read, I managed to work out an Oracle9 persistance configuration for FNH that has worked out quite well.  With that in hand, here’s a summary of how things hooked up.  Any feedback would be greatly appreciated as most of my learning has been, in my opinion, the best kind—trial and error. ๐Ÿ™‚

Also, I’m using various bits from the S#arp Architecture project; however, not everything—remember, I just need readonly access and the amount of noise for all of the libraries was far more than I needed.  I’ve also made several modifications to things such as the PersistentObject and NHibernateSession to include more specific casing required by our organization.

Note: I’m not using the AutoMap features of Fluent NHibernate.  Why?  At this time, our data structure is VERY wonky (vendor controlled data structure, no real rhyme or reason to it, readonly access), so I have a TON of “TheColumnNameIs” and such to map the properties to the oddball data field names.  I am going to hit up the AutoMap features on my next project to better understand them. ๐Ÿ™‚

Part #1 – [Code Here]

[Fact]
public void Fetch_A_Report_By_Id()
{
       IReportRepository stubRepository =
              MockRepository.GenerateStub<IReportRepository>(); 

       Report stubReport =

              MockRepository.GenerateStub<Report>();

 

       stubReport.Id = 140;

           

       stubRepository

              .Expect(x => x.Get(140))

             .Return(stubReport);

 

       var report = stubRepository.Get(140);

 

       report.Id.ShouldBeEqualTo(140);

}

A quick, simple test that looks for a repository and grabs a single entity based on Id. 

At this point, I need an IReportRepository that has a Get method and returns a Report entity.

public interface IReportRepository : INHibernateRepository<Report>

{

}

I could simply call NHibernateRepository<Report>() (or INHibernateRepository<T> in this case) directly; however, I prefer to create entity-based repositories.  I suppose if I had an entity that would NEVER have it’s own specific methods, then I’d reconsider, but I don’t like to mix access methodologies around.

Next, our Repository needs a Report object.  Remember, just the basics.

public class Report : PersistentObject

{

}

Since our Id field comes from the PersistentObject base class, adding it again is unnecessary.

With our Test, IReportRepository, and Report entity objects—we’re now flying green.  At this point, everything is mocked using Rhino Mocks (v3.5).

Passing Test!

Now, let’s try an integration test and hit the database using a bit of test data.

Part #2 – [Code Here]

[Fact]

public void Fetch_A_Report_By_Id_From_Database()

{

       var repository = new ReportRepository();

       var report = repository.Get(140);

       report.Id.ShouldBeEqualTo(140);

}

For this test, we need an implementation of our IReportRepository, ReportRepository:

public class ReportRepository : NHibernateRepository<Report>

{

}

The plumbing of the data connection also needs to be hashed out.  Fluent NHibernate makes configuring NHibernate very easy.

Setting up the Entity Map

Generating the mapping files is as simple as using a couple of virtual methods.  Id, Map, References, etc. will grow to be your friends.

public class ReportMap : ClassMap<Report>

{

       public ReportMap()

       {

              CreateMap();

       }

 

       private void CreateMap()

       {

              WithTable(“Reports”);

              Id(x => x.Id);

       }

}

In a few short lines of code, this has told the Fluent NHibernate API to create a mapping file for the Report entity, to use the Reports table, and to assign the data from the Id column to the Id property of the entity.  Good stuff.

Setting up the Configuration to the Database

Replacing the challenging XML syntax is a VERY useful, fluent configuration API.  I’m using a modified version of Init that reslugs in a default configuration since we’re packaging these configurations for internal use.

public static class ExampleConfiguration

{

       public static Configuration Default

       {

              get { return Production; }

       }

 

       public static Configuration Production

       {

              get

              {

                     var config = new Configuration();

 

              MsSqlConfiguration.MsSql2005

                    .ConnectionString

                        .Database(“ExampleDB”)

                        .Server(“DBServer”)

                        .Username(“DBLogin”)

                        .Password(“DBPassword”)

                        .Create

                    .ConfigureProperties(config);

              return config;

              }

       }

 

       public static void Init(ISessionStorage storage)

       {

              Init(Default, storage);

       }

 

       public static void Init(Configuration configuration,

                               ISessionStorage storage)

       {

              // Any of the maps will do for the assembly mapping.

              NHibernateSession.Init(

                     typeof(ReportMap).Assembly, configuration, storage);

       }

}

Default – Set which of the configuration is the default; called by the overloaded Init method.

Production – Set to the production; you could have Test, AnotherTest, or whatever else your environment needs.  The actual Configuration is using Fluent NHibernate’s PersistanceConfiguration to generate the configuration.

Init(ISessionStorage) – An overloaded Init that calls the default configuration and passes the parameter session storage to NHibernate; this calls …

Init(Configuration, ISessionStorage) – Calls the base NHibernateSession.Init.  This takes an Assembly, the configuration we’re passing it, and the ISessionStorage.

Is there a better way?  If there’s a better way to get the Assembly passed along, I’d LOVE to know.  I’m using this methodology since I keep all of my maps in the same library, but if one found its way into another library, this would break.

Initializing the Configuration

With that configured, I put the Init into the constructor for our test (using xUnit, constructors > [SetUp] :P).

public RepositoryBuildUpExample_2()

{

       ExampleConfiguration.Init(new SimpleSessionStorage());

}

SimpleSessionStorage is a S#arp Architecture snippet for mocking NHibernate; works fantastic.

In a production application, such as an ASP.NET Web site, you would initialize the session in Session_Start or Application_Start and pass along a storage mechanism to save it in .NET session state (or another means).

That’s it—everything’s in place, let’s rerun our test!

Fluent NHibernate Example #2

Excellent.

At this point, further requirements flush out:

  • additional “Get” methods which are added to the ReportRepository,
  • additional properties (columns) for the entity,
  • and, of course, the tests that determine what code is needed.

For the “finished” example, you can download the [code here].

PersistanceConfiguration for Oracle/Fluent NHibernate

December 4, 2008 1 comment

On Tuesday, I mentioned that I created a custom PersistanceConfiguration (based on the template for MS SQL) to connect to Oracle.  I had a few individuals email me, so I went ahead and tossed the code out on Google Code for everyone.

Feel free to download the source here.

The class derives FluentNHibernate’s PersistanceConfiguration<T> and uses the Oracle.DataAccess (ODP) driver. 

To use it, run through just like the MS SQL version.  I did, however, add an OtherOptions property to pass caching, pooling, and other Oracle-specific parameters.  I could have put each to a separate property (and may in the future)—as soon as I can get F-NHibernate fully working. Heh.  Priorities, right?

// Add our Oracle configuration to the NHibernate Config.

var oracleConfiguration = OracleConfiguration.Oracle9

.ConnectionString

      .Server(“server”)

      .Port(1521)

      .Instance(“instance.here”)

      .Username(“user”)

      .Password(“p@$$w0rd”)

      .OtherOptions(“Statement Cache Size=50;”)

      .Create;

oracleConfiguration.ConfigureProperties(config);

config.AddMappingsFromAssembly(Assembly.Load(_mappingAssembly));

Fluent NHibernate With Oracle – An Answer…

December 3, 2008 1 comment

Yesterday, I posted up a real annoying issue with getting Fluent NHibernate working with Oracle.  After dinking most of the evening, I found (as with most things) that the issue had little to do with NHibernate and a great deal to do with my lack of understanding.

Ahh, the joys of learning.

So, here’s where I glitched.

1. The ClassMap needs more than to have public constructors—but must be public itself. 

public class StudentMap : ClassMap<Student>

{

       public StudentMap()

       {

              WithTable(“Students”);

 

              Id(x => x.Id, “pupil_number”)

                     .GeneratedBy.Native();

              Map(x => x.FirstName, “first_name”);

              Map(x => x.LastName, “surname”);

 

       }

}

Whoops.

2. The connection string is touchy.  My original connection string looked like:

@“User Id={0};

Password={1};

Pooling=True;

Enlist=False;

Statement Cache Size=50;

Min Pool Size=10;

Incr Pool Size=5;

Decr Pool Size=2;

Data Source= (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
(HOST={2})(PORT={3})))(CONNECT_DATA=(SERVICE_NAME={4}))”

Unfortunately, that doesn’t seem to work with the non-ODP driver (aka: the Microsoft driver).  Statement Cache Size and the Pooling Size are unknown parameters.  That’s TOTALLY understandable and is easy to fix.

For now, I can simplify this to:

@“User Id={0};

Password={1};

Pooling=True;

Data Source= (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
(HOST={2})(PORT={3})))(CONNECT_DATA=(SERVICE_NAME={4}))”

I’ll work out the ODP drivers as a next step..

That’s it!

With those two changes, my tests pass without any problems AND return the correct information from our database:

Passing Fluent NHibernate Test

Fluent NHibernate With Oracle – A Question…

December 2, 2008 3 comments

Answer found!  Read more here.

After success with standard NHibernate, I quickly became enraptured with the cleaner Fluent NHibernate API.  No more XML; however, I have had VERY limited (read: none) success getting this working against Oracle—especially against our crazy Oracle environment (of which I have no control and readonly access).

Here’s what I have:

A basic ClassMap of a Student object.

class StudentMap : ClassMap<Student>

{

       public StudentMap()

       {

              WithTable(“Students”);

 

              Id(x => x.Id, “pupil_number”)

                     .GeneratedBy.Native();

              Map(x => x.FirstName, “first_name”);

              Map(x => x.LastName, “surname”);

 

       }

}

A basic Student object.

public class Student

{

       private Student() { }

 

       public virtual int Id { get; set; }

       public virtual string FirstName { get; set; }

       public virtual string LastName { get; set; }

}

Note: My constructor is private because this SHOULD be a readonly object.  Setting it public doesn’t seem to matter either. ๐Ÿ˜ฆ

A basic data provider.

public class SISDataProvider

{

       public ISession Session;

 

       public SISDataProvider(ISession session)

       {

              Session = session;

       }

 

       public T GetById<T>(int id)

       {

              Session.Flush();

              return Session.Get<T>(id);

       }

}

No save functionality—again, we just have readonly access to this database.

A basic session manager.

public class SISSessionManager

{

       private readonly string _mappingAssembly;

       private readonly ISessionFactory _sessionFactory;

 

       public SISSessionManager()

       {

              _mappingAssembly = “SIS.Domain”;

              _sessionFactory = GetSessionFactory();

       }

 

       public ISession GetSession()

       {

              return _sessionFactory.OpenSession();

       }

 

       private ISessionFactory GetSessionFactory()

       {

              var config = new Configuration();

 

              var configuration = OracleConfiguration.Oracle9

                .ConnectionString

                    .Server(“server”)

                    .Port(1521)

                    .Instance(“instance.name”)

                    .Username(“user”)

                    .Password(“password”)

                    .Create

                .ConfigureProperties(config);

 

              configuration.AddMappingsFromAssembly(Assembly.Load(_mappingAssembly));

 

              return configuration.BuildSessionFactory();

       }

}

The OracleConfiguration is based on a FluentNhibernate.Cfg.PersistanceConfiguration that I created that calls the OracleClientDriver (not the ODP; that’s OracleDataClientDriver—I’m simply wanting to get the architecture working for now and I’ll dink with increasing performance with ODP as the next step).

Finally, the test.

public class creating_a_student

{

       private SISDataProvider _provider;

       private SISSessionManager _sessionFactory;

 

       public creating_a_student()

       {

              _sessionFactory = new SISSessionManager();

              _provider = new SISDataProvider(_sessionFactory.GetSession());

       }

 

       [Fact]

       public void with_a_valid_student_id_selects_the_correct_student()

       {

             var sut = _provider.GetById<Student>(12345);

             sut.Should_Not_Be_Null();

             sut.Id.Should_Be_Equal_To(12345);

       }

}

Unfortunately, all that and I get an error:

creating_a_student.with_a_valid_student_id_selects_the_correct_student : Failed

XunitException: NHibernate.MappingException : No persister for: SIS.Domain.Student

After some debugging, the Sis.Domain.Student is being added to the Mapping collection, but I’m not sure if that’s the problem or not.  A Google of “no persister” pulls up a few NHibernate hits for not having the XML files set to Embedded Resource, which isn’t my problem here—is it?  I thought Fluent NHibernate escaped XMLHell.

I’d appreciate any guidance on this—I’m stumped.

Using Oracle ODP with NHibernate From a C# Class Library

November 7, 2008 2 comments

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

November 6, 2008 1 comment

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.

Handling Sessions Objects with a Custom Session Manager

September 18, 2008 Comments off

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? ๐Ÿ™‚