Archive

Archive for the ‘.net 3.0’ Category

Crazy Way To Set Display Order From an Enum

I’m sure someone has a better way to do this and I’m all ears; however, this seems to ‘work’ and performs well enough (YAGNI fully applied).

We have an Enum of our different “school levels”–elementary, middle, high schools, special schools, etc.Β  Since the Enum’s values correspond to the data values in our student system, their display/alphabetical orders do not match the common order (e.g. High School = 4, Middle School = 5).

I came up with a simple attribute that’s added to the Enum to “specify” display order and it’s worked like a champ for the past year or so.

[Description("Elementary")]
[DisplayOrder(1)]
Elementary = 2,

[Description("Middle")]
[DisplayOrder(2)]
Middle = 5,

Not at all fancy.

However useful it is at looping and providing context in code, what about using it for ordering OTHER “level” information from another source?Β  So far, I haven’t found a clean way.

The “Solution”?

Use the index of our already-ordered Enum list.Β  In this instance, our model’s SchoolLevel property matches the Description of the Enum.

            var levelsInOrder = Enum<level>.ToList();
            // AutoMapper mappings, etc.

            model.Data = data
                .OrderBy(x => levelsInOrder
                    .FindIndex(z => z.Description() == x.SchoolLevel));

Is it perfect? No, but it works. I could probably even refactor the Enum list and FindIndex call outΒ for a bit more clarity.

        model.Data = data.OrderBy(x => x.GetDisplayOrder(x.SchoolLevel));

        ...

        private int GetDisplayOrder(string level)
        {
            return Enum<level>.ToList().FindIndex(x => x.Description() == level);
        }

Is there a better way?

Categories: .net 3.0, c#, LINQ Tags: , ,

Filtering an Enum by Attribute

July 9, 2009 Comments off

I had a curve ball thrown at me this morning—changing requirements.  It happens and was easily solved by a couple of custom attributes and a helper method.

UPDATE: I’ve updated the code (and explaination) for FilterEnumWithAttributeOf below to tidy it up a bit.

In our current project, there is an enum of standard, static “periods” (times of days students are in school).  Easy enough.

BeforeSchool = 0,
FirstPeriod = 1,
SecondPeriod = 2,
etc.

But what happens if we want to “query” our list down a bit… say a certain group only wanted a subset of the “periods”.

I could create an entirely different Enum — Group1Period and Group2Period.

But then handling things in FluentNHibernate’s automapping would get freaked out with the Period property.

So, what about a custom attribute?

  1. I can assign multiple custom attributes to the same Enum field so I can be in Group1 and Group2 at the same time.
  2. I can keep the same Enum “Period” for my ORM layer.
  3. Now how do I query it down…?

Here’s an abstracted example of how the enum looks right now:

public enum Period

{

    [Elementary][Secondary]

    [Description(“Before School”)]

    BeforeSchool = 0,

 

    [Elementary]

    Homeroom = 12,

 

    [Secondary]

    [Description(“1st”)]

    First = 1,

}

Elementary and Secondary (our two groups, in this case) are “logicless” attributes (I’m just looking at them as flags, not passing/storing information).

[AttributeUsage(AttributeTargets.Field)]

public class ElementaryAttribute : Attribute

{

}

 

[AttributeUsage(AttributeTargets.Field)]

public class SecondaryAttribute : Attribute

{

}

Now, to filter out those pesky periods based on the attributes.

Update:

Old Code!

public IEnumerable<TEnum> FilterEnumWithAttributeOf<TEnum, TAttribute>()

{

    foreach (var field in

        typeof (TEnum).GetFields(BindingFlags.GetField |

                                 BindingFlags.Public |

                                 BindingFlags.Static))

    {

        foreach (var attribute in

            field.GetCustomAttributes(typeof (TAttribute), false))

        {

            yield return (TEnum) field.GetValue(null);

        }

    }

}

New Code!

public static IEnumerable<TEnum> FilterEnumWithAttributeOf<TEnum, TAttribute>()

    where TEnum : struct

    where TAttribute : class

{

    foreach (var field in

        typeof(TEnum).GetFields(BindingFlags.GetField |

                                 BindingFlags.Public |

                                 BindingFlags.Static))

    {

 

        if (field.GetCustomAttributes(typeof(TAttribute), false).Length > 0)

            yield return (TEnum)field.GetValue(null);

    }

}

Why new code?

Well, after looking over the code, I don’t need to iterate through each attribute, simply see if the field contains it (Length > 0).  If it does, then return it.  That cuts a loop out of our code and performs the same function.  I also added two generic constraints.  You can’t constrain by Enum, but struct works well.

I’m passing in two generics in this case—TEnum, which is the type of the of the Enum and TAttribute.. the type of the attribute.  Yeah, I realize that my creativity of naming is pretty low.  Work with me here, alright? πŸ˜‰

Past that, the loops are pretty easy.

  1. Loop through each field of the enumeration.  Return the field (GetField) and be sure to check Public and Static fields.
  2. Loop through each custom attribute on each field (returned by GetField) and only return the fields that match the type of our attribute.  I pass along the false parameter (do not inherit) because I’m not interested in inherited attributes. You could leave this as true. YMMV.
  3. If the field’s attribute’s contains our type, yield out the actual Enum value (a string of the field isn’t as useful).

Now, for using it…

var enums = FilterEnumWithAttributeOf<Period, ElementaryAttribute>();

 

foreach (var period in enums)

{

    Console.WriteLine(“{0}, {1}”.AsFormatFor(period, (int)period));

}

Easy enough.  ElementaryAttribute returns:

BeforeSchool, 0
Homeroom, 12
AfterSchool, 10
etc..

Running the same code, but asking for SecondaryAttribute returns:

BeforeSchool, 0
First, 1
Second, 2
etc..

Sweet.

Tags: , ,

A Flexible “Is In Range” Extension Method

I’m working out some business rules for an application that allows the end user to specify whether or not to direct records by the first letter of the last name of a student or by the grade of the student.

The quick extension method looks like this:

public static bool IsInRange<T>(this T value, T start, T end)

where T: IComparable<T>

{

return value.CompareTo(start) >= 0 && value.CompareTo(end) <= 0;

}

Our tests:

[Fact]

public void IsInRange_returns_correct_boolean_for_comparison()

{

9.IsInRange(1, 10).ShouldBeTrue();

“L”.IsInRange(“A”, “J”).ShouldBeFalse();

“A”.IsInRange(“A”, “A”).ShouldBeTrue();

“B”.IsInRange(“A”, “A”).ShouldBeFalse();

12302.IsInRange(1, 10).ShouldBeFalse();

 

“Bob”.IsInRange(“A”, “A”).ShouldBeFalse();

“Smith”.IsInRange(“A”, “Z”).ShouldBeTrue();

}

Everything works well… I haven’t tested all of the permutations and types yet… but it gets me out of the jam I’m in right now.

Is there a better way? πŸ˜€

HTML Formatting and Spacing in ActiveReports

March 6, 2009 1 comment

ActiveReport’s RichTextBox is great for presenting HTML-styled content on PDF reports; however, there seems to be a snag with a few of the HTML tags and how the RichTextBox translates the commands to HTML.

To print out a bit of HTML (from a field), I have the following StringBuilder my details_Format:

builder

       .AppendFormat(

       @”{0}On {1}, <strong>{2}</strong> wrote: <br/>{3}<br/><br/>{4}”,

       […]);

However, the <strong> tags are not properly rendering spaces between them:

Issues with Spacing

There seems to be an existing notice on the DataDynamics forums (here) regarding the spacing, but it’s from 2007–-I’d assume it’s been fixed by now; however, I can’t find it in any of the AR3.0 release notes.

So what’s the fix?

Force the spaces in with non-breaking space commands.

       @”{0}On {1},&nbsp;<strong>{2}</strong>&nbsp;wrote: <br/>{3}<br/><br/>{4}”,

Bingo!

Fix With Spacing

Part 2: Converting Generic Collections to CSVs

February 6, 2009 1 comment

Part 1 | Part 2

In my last post, I wrote up the tests needed to meet our customer’s requirements, now I’m ready to flush out the tests.

Objective #1 – Export Collection to CSV With All Properties

Each of my tests implement one of two extension methods, ToDelimitedFile and ToDelimitedRow.  Collections focus on File whereas objects (singles) use the Row. 

Unfortunately, I couldn’t find a 100% accurate way to use the generic constraints—too bad we can’t put in “where T : !ICollection<T>”  Hence the separate methods.

For me, extension methods sit outside of my actual classes in their own happy static {whatever}Extensions class.  The CSV Conversions are no different.

For Test #1 to pass, we need to implement the extension method.

public static string ToDelimitedFile<T>(this ICollection<T> convertible)

{

       return DelimitedExporter.SerializeCollection(convertible);

}

This paves the way for creating our next class and method, DelimitedExporter and SerializeCollection.  The DelimitedExporter class will contain all of the methods and logic for converting our collections into CSV “lines”.  Let’s implement SerializeCollection real quick with some dummy data and rerun the test.

public static string SerializeCollection<T>(ICollection<T> convertible)

{

       return “Name,Level”;

}

Pass!  Test passes!

Now, of course, since the test passes, we’re ready to flush out the details of the SerializeCollection method.

Creating the Header Rows

Since we know we’ll be working with strings and doing a large number of appends, let’s start out by creating a StringBuilder to hold all of that text information.

public static string SerializeCollection<T>(IEnumerable<T> convertible)

{

       var stringBuilder = new StringBuilder();

 

       //grab properties of the method to create columns

       var columns = typeof(T).GetProperties();

 

GetProperties is a method on Type that returns all public properties as PropertyInfo objects.  These properties will be used to create the column header names for our CSV.

       // build header row

       stringBuilder.Append(BuildHeaderRowFrom(columns));

 

So let’s “build” our header row.  I’ve extracted this into a separate method from the start—you could have one mega method and refactor it down later.

 

private static string BuildHeaderRowFrom(IEnumerable<PropertyInfo> columns)

{

       var headerString = string.Empty;

       var counter = 0;

       foreach (PropertyInfo column in columns)

       {

              counter++;

             headerString += column.Name;

             if (counter != columns.Count)

                     headerString += “,”;

       }

       headerString += Environment.NewLine;

 

       return headerString;

}

The BuildHeaderRowFrom method takes the PropertyInfo enumeration from our GetProperties() call and iterates through it, capturing the Name of each property and appending it to a string.

Let’s close up the SerializeCollection() method …

       return stringBuilder.ToString();

}

… and run the test again and everything should pass up to this point.

Now we can focus on the data rows.

Creating the Data Rows

Our next task in SerializeCollection is to flush out how each enumerable object will be converted into a row in our CSV.

After our BuildHeaderRowsFrom() method, let’s now append the data rows with:

       // build item rows

       stringBuilder.Append(BuildDataRowsFrom(collection, columns));

BuildDataRowsFrom will take the original collection of objects (an IEnumerable<T>) and the columns we parsed for the header as parameters.

private static string BuildDataRowsFrom<T>(

       IEnumerable<T> collection,

       IEnumerable<PropertyInfo> columns)

{

       var rowString = string.Empty;

       foreach (T item in collection)

       {

              int counter = 0;

              var columnCount = columns.Count();

             foreach (PropertyInfo column in columns)

             {

                     counter++;

                     var value =

                           column.GetValue(item, null) ?? string.Empty;

 

                     // Append column value to the row.

                     rowString += “{0}”.AsFormatFor(value);

 

                     // Append delimiter if _not_ the last column.

                     if (counter != columnCount)

                           rowString += “,”;

              }

              rowString += Environment.NewLine;

       }

       return rowString;

}

Note: I could use a StringBuilder inside of this; however, the StringBuilder seemed to take a bit longer with the tests of 50,000ish records (max in the system I was designing this for).  A later revision may be to further examine ways to improve performance.

 

So, what’s all this do?

 

For the most part, it reads as a sentence:  For each item in the collection, loop through each known column and fetch the value from that item.  If the item is null, simply return an empty string. 

 

Since I’m using IEnumerable<T> rather than ICollection<T>, I don’t have access to a Count property (without calling the Linq extension method, so I’ve moved that outside of the foreach loop.  Perhaps there’s a better generic collection to be using, but that’s for later revisions.

 

Again, run our test again, and it should pass AND we should now have data.

 

can_convert_list_of_objects_to_csv : Passed

*** ConsoleOutput ***
Name,Level
SchoolA,Elementary
SchoolB,Elementary
SchoolC,Elementary
SchoolD,Elementary

 

Excellent.

 

That’s it for this post.  In the next part, I’ll start in on the second objective—being able to specify which parameters are picked up by the DelimitedExporter.

 

 

Part 1: Converting Generic Collections To CSVs

February 6, 2009 1 comment

I recently had a request to allow “exports” of lists from one application to the user in CSV (comma separated value) format.  After a bit of dinking, here’s what I came up with; however, I’m sure a bit more work will find that it’s overkill. πŸ™‚

Starting Off With The Tests

So what did I want to accomplish?  I had three objectives:

  1. Export a collection of objects (IList, ICollection, IEnumerable, etc) to CSV with all “properties”.
  2. Export a collection and be able to specify the properties to export.
  3. (optional) Export a single object to CSV with the same two requirements above (1, 2).

#1:

[Fact]

public void can_convert_list_of_objects_to_csv()

{

       var repository = new SchoolRepository();

       var schools = repository.GetBySchoolLevel(Level.Elementary);

 

       var csvOutput = schools.ToDelimitedFile();

 

       // check that the CSV has the headers

       // of the properties of the object

       csvOutput.ShouldContain(“Name,Level”);

}

#2:

[Fact]

public void can_convert_list_of_objects_to_csv_with_parameters()

{

       var repository = new SchoolRepository();

       var schools = repository.GetBySchoolLevel(Level.Elementary);

      

       var csvOutput = schools.ToDelimitedFile(“Name”);

       csvOutput.ShouldContain(“Name”);

 

       Console.Write(csvOutput);

}

#3:

[Fact]

public void can_convert_a_single_object_to_csv()

{

       var repository = new SchoolRepository();

       var school = repository.Get(120);

 

       var csvOutput = school.ToDelimitedRow();

       csvOutput.ShouldContain(“Great School,High”);

 

       Console.Write(csvOutput);

}

In the next post, we’ll begin flushing out our tests.

 

 

Setting the ViewPort for iPhone/iTouch Ready Web Sites

January 13, 2009 Comments off

Scenario:

After rolling out two new web applications targeted for WindowsMobile and Blackberries, we had a request to test and support Apple iPhone/iTouch devices.  Not a big deal, or so I thought.

Unfortunately, Safari on these devices displayed properly, but every page required zooming and was almost impossible to read.  There had to be a way to get Safari to respect the set width of the page rather than scale it out.

Solution:

Michael: “are you setting the viewport?”

Thanks to Google and a bit of help from a friend (thanks Michael!), the mysterious solution was just a meta tag away.  The best place to start would be the “Safari Web Content Guide for iPhone OS”.  I had found bits of this document elsewhere, but the information about the Viewport tags are extremely helpful.

The default viewport width is 980px; however, you can hard code the width of your page.  I placed the following tag in the <head> section of my MasterPage for the mobile site.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=350px” />

That worked; however, the HTML elements (buttons, selects, etc) were still far too small.  It seems that “fit to device” is more explicitly expressed with the device-width value.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=device-width” />

device-width not only fit the text to the screen, but also properly scaled the elements as well.

Excellent. πŸ™‚

I need to fully read that Safari Web Content Guide to see if there are other wonky tags for iDevice goodness. πŸ˜‰

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