Jeremy Miller on Persistence Patterns

Remember that article on persistence patterns I promised a while ago? Well, Jeremy Miller beat me to the punch (which comes as no surprise, since despite my efforts I only post once in a blue moon). Check out his MSDN article here.

I’ve been fighting other battles in the mean time, with some success. More on that later.

Cheers,

Matei


Cold!

Oh boy is it cold out there! It was pretty insane out there today, about –40 with the windshield. We used to have a joke in Romania that goes like this:

What’s the difference between Canada and Siberia?
You go to Canada by you own free will!


Template expansion with nAnt

If you have a nAnt driven build system, or are planning on putting one together, template expansion can be a very useful tool. It helps you account for variability in the build environment, be it on developer machines or the build server. I’ve posted a couple of links before for nAnt, (see JP’s excellent tutorial series) but this one keeps coming up so I figured I’d dedicate a post to it.

You can simply define properties in your build file and .config templates (or other templates) with tokens to be replaced with property values. When you copy the template file over, the tokens can be replaced by their respective property values, using the filterchain feature.

Here’s a very simple file that doesn’t do much besides copy a .config file over to the deploy folder and expand the tokens in it; right below it there is a section of the web.config.template we will use;

   1: <?xml version="1.0"?>
   2: <project name="eploringormpatterns">
   3:   <property name="connection.string" value="Data Source=ARES;Initial Catalog=ormpatterns;Integrated Security=True" />
   4:  
   5:   <target name="expand.template" default="true">
   6:     <copy file="src\web\web.config.template" tofile="deploy\web\web.config">
   7:       <filterchain>
   8:         <replacetokens>
   9:           <token key="connection.string" value="${connection.string}" />
  10:         </replacetokens>
  11:       </filterchain>
  12:     </copy>
  13:   </target>
  14: </project>

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <connectionStrings>
   4:     <add name="ormpatterns" connectionString="@connection.string@"
   5:         providerName="System.Data.SqlClient" />
   6:   </connectionStrings>
   7: </configuration>

When you run this build file the web.config.template file will be copied over to “deploy\web\web.config” and the @connection.string@ token will be replaced with the value in the property with the same name.

It would be nice if we didn’t need to touch the .build file every time we needed to customize a property. Well, there’s a way to do that. We can extract the properties that vary in a separate file, say local.settings.xml and include that in the build file. That way we only need to change a tiny file to make the build run in our environment. We end up with something like the file below:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <properties>
   3:   <property name="connection.string" value="Data Source=ARES;Initial Catalog=ormpatterns;Integrated Security=True" />  
   4: </properties>

and in the build file we include the local.settings.xml file like so:

   1: <include buildfile="local.settings.xml" />

Now we have one simple file to edit in order to account for changes in the environment and we never have to touch the build file for small changes.

On a final note, when setting up your nAnt build system, try to avoid folders with spaces in the name. This will save you much pain and suffering,


Data types and you

I promised myself I’ll stop posting trivialities, but I feel compelled to discuss double versus decimal again. I see a lot of people use double or float for money amounts. Don’t! Double, or float for that matter, doesn’t have enough precision to handle financial calculations without a lot of rounding errors. The decimal data type provides significantly more precision than the other two. So if you are wondering where those pennies went, well it’s time to switch to decimal.

You should know that there are some performance penalties associated with this, as it is a 128 bit value. Also, ran into an interesting detail in the docs: the decimal struct is not guaranteed to be thread safe on all platforms! What gives? Apparently the value is too large to be assigned in one atomic operation. Does anyone know more about the mechanics of this? Please share!


Structs and interfaces

I ran into an interesting tidbit the other day: a couple of structs implementing and interface. That just seems like asking for trouble to me, structs are value types and interfaces are reference types. Something tells me there could be some subtle issues associated with this. It’s pretty clear that boxing will occur when you pass a value type as a reference type, but I’m sure that’s not the only issue we’ll see here. Time for a quick study.

Here’s the interface we’ll be implementing:

   1: public interface IPlayer
   2: {
   3:     string Name { get; set; }
   4:     string Club { get; set; }
   5:     int Age { get; set; }
   6:  
   7:     void Transfer(string newClub);
   8: }

And here’s a real simple implementation for it:

   1: public struct Player : IPlayer
   2: {
   3:     public string Name { get; set; }
   4:     
   5:     private string club;
   6:     public string Club
   7:     {
   8:         get { return club; }
   9:         set { club = value; }
  10:     }
  11:  
  12:     public int Age { get; set; }
  13:  
  14:     public void Transfer(string newClub)
  15:     {
  16:         club = newClub;
  17:     }
  18: }

So we’re just going to go ahead and create an instance of a player. Once we have that we’ll print the club he’s currently playing for and we’ll transfer him to a different club (and make a lot of money in the process).

   1: Player player = new Player {Age = 20, Club = "AC Milan", Name = "Marco van Basten"};
   2: player.Transfer("Ajax Amsterdam");
   3:  
   4: Console.WriteLine(player.Club);

It’s not too hard to guess this will output “Ajax Amsterdam”. Now what happens if we transfer Marco back to AC Milan, but using the IPlayer interface now? Let’s see.

   1: IPlayer copy = player;
   2: copy.Transfer("AC Milan");
   3:  
   4: Console.WriteLine(player.Club);

Looks like Marco still plays for Amsterdam even though we  just transferred him to Milan. Tough! Well, what happened? The implicit cast created a temporary object we updated and threw away. Not good. Now if we changed the Player struct to a class it would all work as expected.

I would stay away from structs implementing interfaces, just make it a class instead.


Search

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010