Cleveland Day of .NET - Saturday May 17th

Cleveland Day of .NET

 

I just found out I'll be giving my presentation on NHibernate at the Cleveland Day of .NET this Saturday.

I'll be making one change to my presentation, in that instead of trying to show all the NHibernate's features in a single project, I'll move to more of a feature-per-mapping model. 

Now I just need to do that... tomorrow.

Data Access with NHibernate code and slides

Day of .Net May 10, 2008 - I'll be there!Thanks to everyone who came to my talk on NHibernate at West Michigan day of .NET.

The code is available over on google code and the slides are available here.

Documentation Links:

NHibernate Documentation - http://hibernate.org/hib_docs/nhibernate

NHibernate Mailing List - http://groups.google.com/group/nhusers

NHibernate In Action - http://manning.com/kuate

Code Links:

I didn't get to see too many sessions myself, but Steven Harman's Rhino Mocks talk convinced me I need to investigate this whole BDD thing.

Boo and Duck Typing

A heated discussion broke out at work today over the pros and cons of allowing the UI to reference the data access layer.  I'm agnostic about this myself, but we have enforced this restriction and thus have a lot of pointless pass-thru methods that need to be maintained.  Without discussing the merits of any of this, I was wondering, theoretically, how we could avoid writing pass-thru methods were we to use a more dynamic language.

Enter boo and its duck typing.

Say I have a TestRepository, and it has a method GetUser:

class TestRepository(): def constructor(): pass def GetUser(name as string): Console.WriteLine(name)

And I have my TestServices, that contains a TestRepository.  I don't want to write the method on TestServices that just calls TestRepository, and maintain it an all of its parameters.


Instead, I can implement the interface IQuackFu, and implement its methods QuackInvoke, QuackSet and QuackGet

class TestServices(IQuackFu): testRepository as TestRepository def constructor(repository): testRepository = repository def QuackInvoke(name as string, args as (object)) as object: # need to parse parameters to handle overloads testRepository.GetType().GetMethod(name).Invoke(testRepository, args) def QuackSet(name as string, parameters as (object), value) as object: pass def QuackGet(name as string, parameters as (object)) as object: pass

Then if I have a service, declared as a duck (a valid type in boo), I can call any method on it and it will be handled by QuackInvoke.

[Test] def can_call_child(): services as duck services = TestServices(TestRepository()) services.GetUser("ignu")

services.GetUser("ignu") calls services.QuackInvoke("GetUser", "ignu") and our test passes:

Selected test: QuackTest.Test.can_call_child ignu

Yay!

Len: 1 Compiler: 0

Actually, scratch that.  This solution works... but it's not the most elegant solution in the universe.   It's more of a draw. 

We'll meet again, compiler.  Mark my words.

len's three stages of feature grief
I realized that when I encounter a new feature, I progress through three distinct phases of grief.

1)  Disbelief:  "Impossible!  It can't be done!"
2)  Mourning:  "Okay... it can be done, but it's going to suck so much!!"
3)  Euphoria: "Wait.... Oh!  Oh!  I know how we can do this.... this is going to be slick."

Sometimes I go through all three phases so quickly I erupt in one incoherent sentence.
A Few NHibernate Gotchas
Some things to watch out for when working with NHibernate...

If you update an NHibernate entity without detaching it first from the session, it will be updated automatically.


         [Test]        
        
public void UpdatedEntityPropertyWillSaveAutomatically()
        {
            Customer customer 
= null;

            try
            
{                
                customer 
_Repository.GetFirst();
                
customer.FirstName = null;  // First Name can not be null, so this will throw an exception
                
_Repository.Flush();  // flush happens also when the session ends.
            
}
            
catch(Exception ex)
            {
                Assert.That(ex.InnerException 
is System.Data.SqlClient.SqlException);
                
_Repository.Clear();                              
                return;
            
}

            Assert.Fail(
"We should never get here, because flushing the repository will throw the exception above.");
        
}

If you do not detach your object from its repository, NHibernate will pass you a reference to the same object.

        [Test]
        
public void IfNotDetachedTwoObjectsHaveTheSameReference()
        {
            Customer c1 
_Repository.GetFirst();
            
Customer c2 _Repository.GetById(c1.ID);

            
c1.LastName +"1";
            
Assert.AreEqual(c1.LastName, c2.LastName);
        
}

        [Test]
        
public void IfDetachedAnObjectWillNotHaveTheSameReference()
        {
            Customer c1 
_Repository.GetFirst();
            
_Repository.Evict(c1);
            
Customer c2 _Repository.GetById(c1.ID);

            
c1.LastName +"1";
            
Assert.AreNotEqual(c1.LastName, c2.LastName);
        
}
CodeRush 3.0!
It looks like only reasons I had doubts about using CodeRush over Resharper have disappeared today.
CodeRush 3.0 ships with two new major features. The first is the new code navigation engine that allows you to easily traverse through method overloads, navigate between base and child classes, jump to the previous or next reference to a member, and much more. Another important enhancement in this release is the new code generation mechanism. You can now first write code using undeclared class and member names and then, with a few clicks or keystrokes, automatically declare the referenced structures. As you can imagine, this feature will be extremely useful for those practicing test-driven development.
C# 3.0, before and after.

Before (C# 2.0):
    public class Speech : EntityBase<Speech>
    {

        
private string _Body;
        public string 
Body
        {
            
get
            
{
                
return _Body;
            
}
            
set
            
{
                _Body 
= value;
            
}
        }

        
private string _ExtendedBody;
        public string 
ExtendedBody
        {
            
get
            
{
                
return _ExtendedBody;
            
}
            
set
            
{                
                _ExtendedBody 
= value;
            
}
        }


        
private User _User;
        public 
User User
        {
            
get
            
{
                
return _User;
            
}
            
set
            
{
                
_User = value;
            
}
        }

        
private SpeechTopic _Topic;
        public 
SpeechTopic Topic
        {
            
get
            
{
                
return _Topic;
            
}
            
set
            
{
                _Topic 
= value;
            
}
        }

    }
After (C# 3.0):

    
public class Speech : EntityBase<Speech>
    {       
        
public string Body {get; set;}
               

        
public string ExtendedBody {get; set;}
       

        
public User User {get; set;}
       

        
public SpeechTopic Topic {get; set;}
    }


Oh Visual Studio 2008, please hurry up.
Dear Recruiters,
If I update my resume on monster.com, please use the phone number provided in said resume and do not look up my current place of employment and ask for me there.

"Oh, he didn't answer his cell phone. I know! I can use Google, search for the company that he currently works for and ask to be transfered!"

My cell phone's already been ringing ten times more often than normal and now I hear, shouted across the office, "Hey Len, Stupid Douchebag from Dumb$h*t Staffing is on line 1 for you."

AKSLJDASLKDJ:AS