PrimeDigit – A Design Blog by Will Shaver

August 20, 2008

Abstract Class Mappings

Filed under: Uncategorized — Will @ 12:05 pm

If you’re running into this error in NHibernate:

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Attempting to parse a null value into an sql string.

Examine your mappings for abstract classes that aren’t implemented, or classes that are marked as abstract in the mappings but not in the c# file. I was refactoring out some abstract classes in the middle and forgot to delete the abstract=”true” line in the mapping.

August 5, 2008

Death to Foo and Bar

Filed under: Uncategorized — Will @ 5:49 pm

I’ve had it with Foo and Bar. They are right out. For too long we programmers have put up with these sorry excuses for example classes in documentation, lectures, examples, and now that TDD is all the rage, tests.

There is no standard for the relationship of Foo and Bar.

Standards in examples and relationships are full of time-saving goodness. Take for example the Northwind database. Recently there’s been a big push for replacing Northwind with some other database standard. One of the chief arguments against the “Not Northwind” mafia are the magic words, “I’m using Northwind for my database”. *Poof* everyone in the audience knows the relationships inherent in the system.

But Foo and Bar have no default relationship. In the NHibernate project there are 8 different Foo classes, 2 Bars, and 1 FooBar. One of those is actually even in the NHibernate.DomainModel namespace, most of the remainder are in the SpecificTest folder. Different developers have created tests relying on Foo and Bar, and when debugging these tests I have no idea what the properties, entities, or relationships should be.

A sampling of different properties shows that some Foos have Descriptions, while others have Names, Words, Numbers. Some have other Foo as children, while others have Bar as children. Sometimes a FooBar will have a Foo or Bar property….

Enough!

Please, if you submit a patch to an Open Source project… or any project for that matter, don’t use Foo or Bar. Use People and Pets, Cities and Houses, Sales Orders and Sales Line Items, Customers and Orders… any number of obvious relationships that readers won’t need to review the class in order to understand. Foo and Bar slow the reader down… even if you’re the one that wrote it.

NHibernate Developer

Filed under: Uncategorized — Will @ 5:39 pm

W00t! I’ve been accepted as a developer of NHibernate. I’m looking forward to helping this project move along as I discover things that I can fix…

July 22, 2008

Your website might suck if

Filed under: Uncategorized — Will @ 2:04 pm

Your website might suck if… it contains the words click here.

Of course… now mine does. Doh!

June 16, 2008

CriteriaByLongAlias

Filed under: c#,NHibernate — Will @ 9:01 am

This simple function cleans up a lot of the Alias sillyness I have fought with in NHibernate.

        public static ICriteria CriteriaByLongAlias(this ICriteria criteria, string field)

        {

            ICriteria byAlias = criteria.GetCriteriaByAlias(criteria.Alias + “_” + field) ??

                                criteria.CreateCriteria(field, criteria.Alias + “_” + field);

            return byAlias;

        }

It is used any time you would previously call CreateCriteria and pass an alias.
Before:
session.CreateCriteria(typeof (Product)).CreateCriteria(“Orders”,”Product_Orders”);
After:
session.CreateCriteria(typeof(Product)).CriteriaByLongAlias(“Orders”);

The alias part is done automatically based on the criteria path. The advantage is that it works recursively, allowing for multiple criteria to be created, and then referenced without duplicates.

ICriteria criteria = session.CreateCriteria(typeof(Product)).CriteriaByLongAlias(“Orders”).CriteriaByLongAlias(“Customer”).Add(Expression.Eq(“Name”, “Ace Hardware”));
criteria.CriteriaByLongAlias(“Orders”).Add(Expression.Eq(“OrderNumber”,12354));

etc.

Note that in order for it to work, you have to create all your subcriteria with it.

-Will

June 4, 2008

Cool Code – Assembly.FindType

Filed under: c# — Will @ 3:06 pm

Here’s an extension to Assembly that I found useful for finding a type. I recommend doing
typeof(TypeInAssembly).Assembly.FindType(“typename”);

    public static class AssemblyExtensions

    {

        public static Type FindType(this Assembly assembly, string typename)

        {

            return assembly.FindTypes(typename).FirstOrDefault();

        }

 

        public static Type[] FindTypes(this Assembly assembly, string typename)

        {

            Type[] types = assembly.GetExportedTypes();

            List<Type> found = new List<Type>();

            foreach(Type type in types)

            {

                if(type.Name == typename)

                {

                    found.Add(type);

                }

            }

            return found.ToArray();

        }

    }

May 20, 2008

I may need a new ringtone

Filed under: Uncategorized — Will @ 1:34 pm

A GUI Interface in VB to Track an IP Address?

April 24, 2008

Internal SQL Server Error

Filed under: Uncategorized — Will @ 4:39 pm

internalservererror.png

Thanks for the ohhh so useful error message SQL server team.

Ass.

April 22, 2008

Contributing to NHibernate

Filed under: c#,Tutorials — Will @ 9:12 pm

Having successfully submitted a few patches to NHibernate [NH-1280][NH-1260][NH-1259], Ayende Rahien asked me to comment on the difficulty of adding a totally new feature, and provide some hints for others. I am by no means an expert on NHibernate, just a regular user so here goes…

My most recent change set was updating the Criteria Query API to allow for queries involving HAVING clauses. In performing this change I also discovered a bug whereby complicated queries would get parameters out of order. In this post I will cover:

  • The feature added (need and implementation)
  • Determining problem need
  • Hints for getting your patch accepted

The Feature

The Criteria Query API provides some valuable tools for creating dynamic queries without doing crazy string manipulation (yuck). I had a situation where I wanted to validate entities to check for duplicates prior to the transaction being committed. Because of the temporal nature of the project I’m working on, I can’t do it with a table constraint or other simple means and need to check valid dates.

To solve it with HQL would involved about 10 lines of messy reflection and string concats where solving it with the criteria API took about 4. Here’s the code:

ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.SetProjection(Projections.ProjectionList()
  .Add(Projections.Max("Id"))
  .Add(Projections.GroupProperty("Name")))
  .ProjectionCriteria.Add(Restrictions.Gt(Projections.Count("Name"), 1));

The resulting SQL for this code should be:

"SELECT MAX(Id), Name FROM Person GROUP BY Name HAVING COUNT(Name) > 1"

Imagine my surprise when this relatively simple Criteria Query failed while the same HQL query succeeded. After examining the SQL it produced I determined that there was no HAVING clause being produced.

Fearing that I was doing something wrong I opened up the source code for NHibernate and performed a textual search for “having” as I knew that at some point it must be produced by the SQL generator. I was unable to locate anything in the Criteria API that was even remotely related to HAVING queries.

Having exhausted that possibility I posted to the google nhusers group to make sure that I wasn’t missing something. After some discussion it was obvious that this was indeed a lacking feature and that it would be appreciated by the community.

Quick Review

  1. Confirm that the problem is with the codebase not with your use of it.
    1. Review the code to determine if it is possible to produce the desired result.
    2. Post to the nhusers group to make sure you’re using the API correctly.
  2. Confirm the problem isn’t solved in the JAVA version. (If it is, import that fix.)
  3. Migrate the discussion to the NHibernate developer list for help.

After determining that it was indeed a problem with the codebase I launched into patching it. I wrote test cases to be able to debug into the code in the Criteria interface. I recommend adding the folder for your tests as:
\src\NHibernate.Test\NHSpecificTest\NH1999
Then migrating it to the specific issue number after you’ve made progress enough to report the issue. This prevents nasty collision problems if someone else takes the next number.
\src\NHibernate.Test\NHSpecificTest\NH1280
I’ve also recently taken to adding a description after the folder such as “NH1291AnonExample” in my latest patch. This makes it easier to determine which set of tests has failed for other developers.

The patch itself is rather complicated and out of the scope of this post as it contained changes to almost 50 files. In writing the patch I tried a couple of different methods for adding my features and even had to revert a couple of files from the source. I worked from the output to the input, backing out from the SQL generator to the individual Criteria and Criterion classes.

As I wrote the patch I made sure that I didn’t negatively impact other use cases. If your patch breaks other tests it won’t be accepted even if it implements “teh best featre evar”! For added tests I merged my changes into both my active work project and the Linq to NHibernate project. Doing so revealed cases that I hadn’t considered in my initial tests and allowed me to add in those tests and deliver a more solid patch.

Quick Review

  1. Write a small set of failing tests first. Step-Into these tests while debugging for where to start coding.
  2. Don’t fear changing the source, you can always revert!
  3. Start at the interface points and work toward the center where actual work is performed.
  4. Make sure all unit tests, including those in other projects are passing.

Before submitting any patch I always go through a cleanup of my changed code. This involved going through my patch file by file making sure that I’m only submitting code that pertains to the patch and only changes things that need to be changed. (Using TortoiseSVN this is quite simple, folder menu -> check for modifications)

I try and keep my formatting changes to a minimum. Resist the urge to re-arrange existing code, convert tabs to spaces etc. While NHibernate and many other open source projects could use some cleanup work, that should be performed by dedicated committers. In our case the organization is loosely tied to the Hibernate project and would make it more difficult to port newer features if the NHibernate code is re-arranged.

Submit the patch and leave a clear explanation of the problem it solves and how it solves it. Best of luck and thanks for contributing to the project!

Quick Review

  1. Clean up your code before you commit by reviewing the changes.
  2. Add your patch the JIRA, documenting the change need and usage.

April 8, 2008

Hiding Your hbm.xml files in Visual Studio (or not)

Filed under: Uncategorized — Will @ 5:54 pm

I had this cool idea. What if I could hide my NHibernate Entity.hbm.xml files behind their respective c# files in the Solution Explorer. This would tidy things up a bit as I’m getting a bit overloaded in my project at work.

It turns out that this is pretty easy to accomplish… visually. Here’s what we’re trying to accomplish:

Standard
Behind
Hidden

Busting out the .csproj file I can edit the file to go from:


<ItemGroup>
<EmbeddedResource Include="Class1.hbm.xml" />
</ItemGroup>

To:


<ItemGroup>
<EmbeddedResource Include="Class1.hbm.xml">
<DependentUpon>Class1.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>

I even found a macro that does it for you rather than having to hack the visual studio project file directly.

Unfortunately it suddenly broke all my unit tests. Turns out that when adding “dependent upon” it does more than just the visual but actually changes the name (and type?) of the file. Here’s what it looks like in Reflector before:
Plain Old XML

Here’s what it looks like after:
Compiled XML

I spent an hour or so on the MSDN trying to figure out how to solve this problem, but I can’t seem to figure out how to do it. It looks like someone else had this EXACT idea and problem.

Anyone have any ideas on how to solve this?

« Newer PostsOlder Posts »

Powered by WordPress