Archive for category nant
SQL Server CE up and running with NHibernate & NAnt
Posted by haugern in compact edition, database, nant, nhibernate, sql server on January 23rd, 2008
I’ve been working to get SQL CE to work with our application lately. This is a great step towards a more painless desktop deployment model for us.
It turned out to be a multi step process, and first out was discovering how to make a SQL CE file.
Creating the SQL Server CE .sdf file
There are two alternatives as I see it:
- Create an empty database with ie SQL Enterprise Manager, and copy it for new deployment
- Create it programmatically at runtime.
We already have a solution folder and a setup for sql-script templates, so we went with #1.
Using NHibernate hbm2ddl NAnt task for the schema
NHibernate has built in support for SQL Server CE, and what you have to do is the following:
- Set the connection.connection_string property.
- Set the connection.driver_class property.
- Set the dialect property.
Our current NAnt build file has had support for SQL Express 2005 & SQL Developer Edition 2005, and our schema target have been doing a great job at creating the proper schema. The hbm2ddl task has been called with the following attributes:
<hbm2ddl connectionstring="${sql.nhibernate.connection}" droponly="false" exportonly="true"> <assemblies> <include name="${directory.build}\ISY.Domain.dll"></include> <include name="${directory.build}\ISY.Infrastructure.dll"></include> <include name="${directory.build}\ISY.Repository.dll"></include> </assemblies> </hbm2ddl>
So I go ahead and set the connectionstring attribute with the correct settings. And it fails miserably:
NHibernate.HibernateException: An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified) —> System.Data.SqlClient.SqlException: An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
Ok, that’s not good. It seems it cannot connect to the server. Checking the ins and outs of the my sql.nhibernate.connection property, I find that it should be pointing to the right file. After some investigation I find out that I miss #2 & #3; setting the correct dialect and driver_class. The hbm2ddl task had default values for dialect and driver_class which works great with both our previously two supported databases. So, I set them both like this:
<hbm2ddl connectionstring="${sql.nhibernate.connection}" dialect="${sql.dialect}" connectiondriverclass="${sql.driver}" droponly="false" exportonly="true"> <assemblies> <include name="${directory.build}\ISY.Domain.dll"></include> <include name="${directory.build}\ISY.Infrastructure.dll"></include> <include name="${directory.build}\ISY.Repository.dll"></include> </assemblies> </hbm2ddl>
Where:
<property name="sql.driver" value="NHibernate.Driver.SqlServerCeDriver" /> <property name="sql.dialect" value="NHibernate.Dialect.MsSqlCeDialect"/>
And we’re there with the hbm2ddl.
PS! Don’t forget to add the SQL CE dll into your folder with NAnt, or else it can’t find the right driver with the above settings (an easy to understand error message will tell you).
Populate the database with default data
After the schema is in place, we populate some tables with default system data from sql script files. For this we use the NAntContrib sql task like this:
<sql connstring="${sql.connectionstring}" delimiter="GO" delimstyle="Line" source="${target}" transaction="${sql.usetransactions}"> </sql>
First, the sql.connectionstring needs to reflect that I am talking to a SQL CE database, and ConnectionStrings.com comes to the rescue once more.
The first obstacle when running the first sql script file is this error:
Error while executing SQL statement.
There was an error parsing the query. [Token line number,Token line offset,,Token in error,,]
Yes, very enlightening indeed! (Note to self: remember good error messages!). In my search for answers, this seems to be “the be all, know it all” error message.
Finally, it dawned upon me; SQL CE doesn’t support stored procs. And for that reason, why would it understand a script which practically could be a stored proc? Luckily, all our default data is inserted with “ordinary” statements, and the sql task does have an attribute called batch which defaults to true. With SQL CE you need to set it to false and you’re good to go with this setup (where the sql.batch property depends on which database is being used):
<sql connstring="${sql.connectionstring}" delimiter="GO" delimstyle="Line" source="${target}" batch="${sql.batch}" transaction="${sql.usetransactions}"> </sql>
Conclusion and further work
All in all, the effort to investigate and include the SQL CE to our array of supported databases is well worth. It will make a one off deployment issues a lot easier with no extra installation, and it is a champ when it comes to our database unit testing and integration testing.
What’s still missing is a script which populates our database with test data. The existing script is not easily split into single statements. We’ll dig into it and I’ll explain it all in a later post!
Automatic versioning with CruiseControl.Net and NAnt
Posted by haugern in continuous integration, cruisecontrol.net, dotnet, nant, source control, tfs on January 11th, 2008
I’ve created a similar setup as David Donald Belcham (a.k.a. igloocoder) mentions in this post for our current project at NOIS.
When I mean similar, we’re using the exact same tools for the job, with NAnt (asminfo task) & CC.NET. But there’s a couple of differences.
New labeller for CC.NET
The first, and minor difference is the labeller. I wanted the versions to work almost as the NAntContrib version task with the automatic build & revision based on day of year and time of day respectively. As most people were running the traditional ymmdd-format for the build, this effectively had to stop at the beginning of 07; 16 bit for the build number breaks that setup. So I settled for an algorithm which won’t break until the year 2066. The major & minor numbers is set manually.
I couldn’t seem to find such a labeller out there, and as I wanted the same number in the CC.NET build-number, and in the assemblies (and in the source control system as well, I’ll get back to that), CC.NET needed to be master. Not finding what I wanted, I created my own labeller for CC.NET, which gives me the build-numbering scheme I wanted.
With the extensibility-points in CC.NET it was great fun, and real easy to deploy my own. Here’s the whole thing:
using System;
using Exortech.NetReflector;
using ThoughtWorks.CruiseControl.Core;
namespace Haugern.Util.CCNet
{
[ReflectorType("versionLabeller")]
public class VersionLabeller : ILabeller
{
[ReflectorProperty("major", Required = true)]
public int Major;
[ReflectorProperty("minor", Required = true)]
public int Minor;
public string Generate(IIntegrationResult integrationResult)
{
if(integrationResult == null)
throw new ArgumentNullException(“integrationResult”);
DateTime now = DateTime.Now;
return Major + “.” + Minor + “.” + ComputeBuild(now) + “.” + ComputeRelease(now);
}
private static string ComputeRelease(DateTime now)
{
return Math.Round((now.TimeOfDay.TotalSeconds/10)).ToString();
}
private static string ComputeBuild(DateTime now)
{
return now.ToString(“yy”) + now.DayOfYear.ToString(“000″);
}
public void Run(IIntegrationResult result)
{
result.Label = Generate(result);
}
}
}
Consistent Build Number
The second difference (well, in his defence, it’s not even mentioned), is that the exact same label should be set back into the source control system. In our case, we’re using TFS Source Control, and with the standard plugin it was easy to apply it there as well.
Now we got this great setup where we can track everything that happens back to the build-number as it is the same across the whole environment:
Application <-> Build server <-> Source Control
Consistent build number across the production line also means every build is a candidate for release.
Should some bug find it way through our thorough unit-testing & qa-scheme into the hands of our customers, finding the right version to search for it will not be a problem!