April 2005 - Posts
After having implemented a data layer in the Data project, it was time to make a real data implementation. A
Sql Server 2000 implementation was the default data source, located in the
Data.SqlServer project.
Enterprise Library was used to provide the data access to
Sql Server. This contained a
Data Access Application Block, which allows configuring the connection string through the
Enterprise Library Configuration tool.
A reference to
Microsoft.Practices.EnterpriseLibrary.Data was needed, together with the
Configuration and
Common assemblies of
Enterprise Library.
Through the
Enterprise Library Configuration tool, an existing App.config was loaded, where the
Data Access Application Block was added. The
database and
server values had to be configured to the actual server being used, together with the database containing the data. Additional connection string properties could be added as well, for example, the
Integrated Security property, which is set to
True.

After saving this file, it was possible to create a data implementation for each
Accessor interface previously defined in the
Data project, as for example this code:
using System;
using System.Data;
using System.Collections;
using MediaService.Logging;
using MediaService.Objects;
using MediaService.Data.Accessors;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Logging;
namespace MediaService.Data.SqlServer {
public class SongDataAccessor: ISongDataAccessor {
} /* SongDataAccessor */
} /* MediaService.Data.SqlServer */
Thanks to the
Enterprise Library Data Access Application Block, the
Sql Server implementation used best practices from the
Microsoft Patterns & Practices group, which followed
Microsoft guidelines and were optimized for performance.
To get an array of objects from the database, a new
Database object had to be created, after which a stored procedure was wrapped, called and read from to get for example
Song objects. This was done with the following code:
public Song[] GetSongs() {
Database db = DatabaseFactory.CreateDatabase("MediaServiceSqlServer");
DBCommandWrapper dbCommandWrapper =
db.GetStoredProcCommandWrapper("GetSongs");
Logger.Write("Retrieving songs.", Category.SqlServer,
Priority.Lowest, 1, Severity.Information);
ArrayList songs = new ArrayList();
using (IDataReader dataReader = db.ExecuteReader(dbCommandWrapper)) {
while (dataReader.Read()) {
songs.Add(new Song(dataReader.GetInt32(0), dataReader.GetString(1),
dataReader.GetString(2), dataReader.GetString(3),
dataReader.GetString(4), dataReader.GetString(5),
dataReader.GetString(6), dataReader.GetInt32(7),
dataReader.GetInt32(8), dataReader.GetInt32(9)));
}
}
Logger.Write(String.Format("Retrieved {0} {1}.", songs.Count,
(songs.Count == 1) ? "song" : "songs"),
Category.SqlServer, Priority.Lowest, 1, Severity.Information);
return (Song[])songs.ToArray(typeof(Song));
} /* GetSongs */
Updating an item by using a stored procedure which uses parameters, was done by using the following code:
public void UpdateSongPlayCount(Int32 songId) {
Database db = DatabaseFactory.CreateDatabase("MediaServiceSqlServer");
DBCommandWrapper dbCommandWrapper =
db.GetStoredProcCommandWrapper("UpdateSongPlayCount");
dbCommandWrapper.AddInParameter("@songId", DbType.Int32, songId);
Logger.Write(String.Format("Updating play count for song: {0}.", songId),
Category.SqlServer, Priority.Lowest, 1, Severity.Information);
try {
db.ExecuteNonQuery(dbCommandWrapper);
} catch (Exception ex) {
Logger.Write(String.Format("Failed to update play count for song: {0}.
Error: {1}", songId, ex.ToString()),
Category.SqlServer, Priority.Highest, 1, Severity.Error);
}
} /* UpdateSongPlayCount */
Using stored procedures made it possible to have another layer of abstraction. This made it easy changing an existing stored procedure to keep track of statistics, without having to change any code of the implementation. At the same time, using stored procedures also protected against
Sql Injection attacks. After all
Accessors were implemented, it was possible to use this implementation by deploying the
SqlServer dll and selecting it as data source.
Any application using data benefits from having a separate data layer. This enables the administrator to select which data source to use. It also makes your application have an advantage, making it easier to sell.
Besides from the advantages for the end-users, it’s also best practices to separate the data layer from your presentation and business logic layer.
To provide the data layer to the application a Data project was added. The layers above the data layer never accessed the real data implementations, but worked with objects which implemented certain data interfaces. This way, it was possible to define all possible data related methods in an interface and afterwards implement them in a real implementation.
A logical grouping was applied when creating the interfaces, starting from a generic
IDataAccessor from which every other interface inherited from.
using System;
namespace MediaService.Data.Accessors {
public interface IDataAccessor {
} /* IDataAccessor */
} /* MediaService.Data.Accessors */
One of the logical sections was for example everything related to
Song objects:
using System;
using MediaService.Objects;
namespace MediaService.Data.Accessors {
public interface ISongDataAccessor: IDataAccessor {
Song[] GetSongs();
Song[] GetQueue();
Song[] GetMostPlayed(Int32 numberOfSongs);
Song[] GetMostPopular(Int32 numberOfSongs);
} /* ISongDataAccessor */
} /* MediaService.Data.Accessors */
Since the other projects did not have a reference to the real data implementations, but only to the
Data project, this project had to take care of loading the correct implementation. Loading the correct class in the real implementation is done by using factories. For every
Accessor interface a factory exists, returning an instance of the data implementation, using the following code:
using System;
using MediaService.Data.Accessors;
namespace MediaService.Data.Factory {
internal class SongFactory: Factory {
internal static ISongDataAccessor Create() {
return Factory.Create(Accessor.Song) as ISongDataAccessor;
} /* Create */
} /* SongFactory */
} /* MediaService.Data */
In the
Data project, there was one
Factory class, responsible for loading the correct assembly containing the data implementation and instantiating the correct
Accessor class. This was done by using
Reflection together with
Configuration to retrieve the location. The location consisted out of the class name and the assembly name, separated by a comma, as for example the location for the
SongDataAccessor:
<SongDataAccessor>
MediaService.Data.SqlServer.SongDataAccessor,MediaService.Data.SqlServer
</SongDataAccessor>
This location data was retrieved by configuration, after which it was separated into assembly and class parts and loaded with
Reflection with the following code:
using System;
using System.Reflection;
using MediaService.Configuration;
using MediaService.Data.Accessors;
using Microsoft.Practices.EnterpriseLibrary.Configuration;
namespace MediaService.Data.Factory {
internal enum Accessor {
Song
} /* Accessor */
internal class Factory {
internal static IDataAccessor Create(Accessor accessorType) {
DatabaseData configData = LoadConfiguration();
if (configData == null) {
throw new ApplicationException("Could not load configuration.");
}
String blockToLoad = String.Empty;
switch (accessorType) {
case Accessor.Song: blockToLoad = configData.SongDataAccessor; break;
}
if (blockToLoad == String.Empty) {
throw new ApplicationException(String.Format(
"Type entry not found for {0}.", accessorType.ToString()));
}
Int32 index = blockToLoad.IndexOf(",");
string typeToLoad = blockToLoad.Substring(0,index);
string assemblyToLoad = blockToLoad.Substring(typeToLoad.Length + 1,
blockToLoad.Length - typeToLoad.Length - 1);
return (IDataAccessor)Assembly.Load(
assemblyToLoad).CreateInstance(typeToLoad);
} /* Create */
private static DatabaseData LoadConfiguration() {
ConfigurationManager.ClearSingletonSectionCache("databaseConfiguration");
return ConfigurationManager.GetConfiguration(
"databaseConfiguration") as DatabaseData;
} /* LoadConfiguration */
} /* Factory */
} /* MediaService.Data.Factory */
All of the
Factories were marked internal because they are just meant for internal workings of the data layer, while all
Accessors remain public because they had to be accessible to implement in the real data implementation.
Besides the
Accessor interfaces, the
Data project also exposed one public class, named Dalc. This class contained static properties for each logical data section, returning an instantiated
Accessor from the configured data source.
using System;
using MediaService.Data.Accessors;
using MediaService.Data.Factory;
namespace MediaService.Data {
public class Dalc {
public static ISongDataAccessor Song {
get { return SongFactory.Create(); }
} /* Song */
} /* Dalc */
} /* MediaService.Data */
After this, it was possible to access data by adding a reference to the
Data project, adding a real data implementation assembly to the deployed location and configuring it. For example, the following code retrieved all songs from the data source:
using MediaService.Objects;
using MediaService.Data;
using MediaService.Data.Accessors;
namespace MediaService.Web {
public class Media {
public Song[] GetSongs() {
return Dalc.Song.GetSongs();
} /* GetSongs */
With this data layer, all details about data access are contained in the real data implementations, while nowhere else there is specific data source code. The entire application works on data objects, which implement the data interfaces, while under the hood, the correct data source is selected through the configuration file.
The Pocket PC I recently received was completely in French, so I figured '
I'll just change this to English'.
It can't be that hard, can it? Apparently it was trickier then I thought.
The Pocket PC has the OS in it's ROM, and it has limited ROM, so no multilanguages in there.
It quickly became obvious to me the ROM had to be flashed with an English version, but where to get it?
I didn't buy the Pocket PC, so asking Dell to give me an English one probably would fail, and from various messageboards I discovered they won't do it anyway.
So, where to get it? From the Dell site I guessed, in the download section there was an English update for Windows Mobile 2003 Second Edition.
Since this update just flashes the ROM and puts the new version in it, I guessed this was ok.
But when trying to flash it, it started complaining about being the wrong language.
Apparently French can only be upgraded to French, and since I don't speak French fluently this wasn't practical :)
So, search engine to the rescue. I found
this post on Aximsite, a site dedicated to Dell Axim resources.
It seemed logical, get the English and French ROM, make the updater believe the English ROM is actually a French language, and flash.
The process looked obvious to me, so, let's get started!
I opened up the French ROM and English ROM in a hex editor and located the differences:

Note:
This is different from the forum post! It's not the first 7 lines you have to copy paste.
Pasting the first 7 lines results in an Integrity Check error. It's enough to change everything before the "AXIM30".
After having modified the English ROM with the new header, I saved it to the French updated directory, overwriting the original French ROM update. (So, now you have a filename which indicates it's a French ROM, but it's actually the English ROM with the French header)
I did the same for the other image (there is a C and an N image).
Now I ran the updater, which did not give me an error about Integrity Check anymore, and also not about wrong language.
It succesfully updated the ROM and after the Pocket PC restarted, everything was English!
So, now I have an English Pocket PC :)
Ofcourse, the disclaimer on my blog applies especially to this post, as this is not something you should do quickly if you have no technical skills.
So: I (David Cumps) cannot be held responsible for any damage what-so-ever that might come from this post. You do this at your own risk.
A while ago I blogged about
Alternate Data Streams and how they are hidden from the users.
At that time, you could presume when an ADS was present, it was something special, because not many
normal files have an ADS attached to it.
But yesterday I got an interesting question about XP SP2 showing a Security Warning when you want to execute something downloaded from the internet.
We guessed Alternate Data Streams were used, so I checked this out and it turns out XP SP2 indeed adds an ADS when you download a file from the Internet.
This stream is called Zone.Identifier and contains the following information:
D:\Tmp>more < TestZip.zip:Zone.Identifier
[ZoneTransfer]
ZoneId=3
Since SP2 did this, it probably means it's a modification to Internet Explorer.
So, I got the Firefox 1.0.3 and downloaded a file with the default settings, and as I guessed, no ADS with Zone.Identifier.
(I believe Firefox doesn't have such thing as Zones, but it would be nice if Firefox added this ADS to let the new Security Warning, informing you it's a downloaded file, come up).
Yesterday I gave a presentation about
eID in .NET, if somebody is interested I have uploaded the presentation together with some sample code to my personal website:
Cumps.beThe purpose of this session is to give an idea about what's possible with the eID card in .NET and what is needed to get it working.
Some background information about eID is provided, after which four possible usage scenarios are described and what is needed to build them.
Note: The code are just technical tryouts, not ment to go straight into production :) Provided "AS IS".
Yesterday I got invited by Microsoft France to Paris, to the Wax Club, to see the French Visual Gaming Finals.
My team mate,
ZogStriP, participated in the High School competition there, so it was very exiting!
It was also a very good experience to learn french ;) And to get to know Paris, where the people are really crazy in traffic. Apparently, stop signs are just for decoration... Green or red, it all means the same :p
They played the games before and played the replay files on big screen, which were also recorded by a french television station. The station is on sattelite and is called GameOne, I don't know yet when they will broadcast it. I'll have to find someone who can digitally record it, because they interviewed me as well :p
So, the High School competition: there were 2 pools, one with 3 games and one with 6. Our best competitor was Z² who lost with a very little difference each time.
In the end, our dll won the High School competition! Resulting in a PDA for my team mate (I'm too old for High School ;p).
But here is where something special happened, he gave me the PDA!
He recently became MVS in France and just received one as well. Isn't it a nice gesture? Microsoft France made a very good choice making him MVS, he really deserves it with this kind of attitude, a real teamplayer. (So, for all French companies reading my blog, go to
his blog and check it out, he would be a great asset for your company!)
After this, it was time for the Open Division.
There, our bot had a hard time. We lost the quarter finals by 1 point, due to a bug causing the AI to stop :/ So, chances for 1st and 2nd were gone. Finally we ended up at the fourth place, because the same bug occured again in the next game, which is really a shame.
One thing is sure, being 4th already is good, especially in France, the country of Visual Gaming, now we only have to fix this bug :p Result of ending on 4th place:
A fingerprint reader and I also got interviewed, in English :p This is really a nice example of "dissolving boundaries" :)
And to finish, here's a picture of ZogStriP and me (ZogStriP right, me left):

To ZogStriP:
Thanks!
I just found the
Microsoft USB Flash Drive Manager trough
Ohad Israeli and when I checked for updates, I got sent to this site, which had something funny on it ;)

I think Google will like it Microsoft promotes their product above
MSN Desktop Search ;)
When developing an application it’s possible to use debug mode to figure out why something is wrong, but when it’s time to deploy the application something else has to be integrated. To solution to this is logging. Implementing good logging functionality will make the Operations people who have to deploy your application happy as well, because they can integrate it into existing monitoring systems.
Enterprise Library was used to implement a flexible logging solution. Thanks to the
Logging and Instrumentation Application Block it’s possible to integrate logging into your code, but decide where to output the log externally from the application. This way it’s possible to log to a flat file, a database, an email address, the event log, a message queue, WMI and custom implementations, without having to change code.
A
Logging project was added to start, to provide some helper constants:
using System;
namespace MediaService.Logging {
public struct Priority {
public const Int32 Lowest = 0;
public const Int32 Low = 1;
public const Int32 Normal = 2;
public const Int32 High = 3;
public const Int32 Highest = 4;
} /* Priority */
public struct Category {
public const String Player = "Player";
public const String Remoting = "Remoting";
public const String Data = "Data";
public const String SqlServer = "SqlServerData";
} /* Category */
} /* MediaService.Logging */
After this, a reference to the
Logging project was added together with a reference to
Microsoft.Practices.EnterpriseLibrary.Logging. A reference to the
Enterprise Library Configuration Application Block was needed as well.
At this point it was possible to log messages by using the following construct:
if (randomSong == null) {
Logger.Write("Unable to select a random song.", Category.Player,
Priority.High, 1, Severity.Error);
} else {
Logger.Write(String.Format("Fetched song: {0} (Random).", randomSong.Path),
Category.Player, Priority.Low, 1, Severity.Information);
}
Similar code had been added throughout the code to provide meaningful feedback. The only thing left was configuring where the log output had to go.
Using the
Enterprise Library Configuration tool, an existing
App.config was loaded and the
Logging and Instrumentation Application Block was added. Under
Client Settings,
LoggingEnabled was to
True.
A new category had to be added, called
Player, by right clicking on
Categories and selecting
New – Category. This is the name that was used in the code to specify which log the output belongs to. It was possible to define multiple categories.
To define where the output had to go to, a new sink was added, called
Player Flat File Sink, by right clicking on
Sinks and selecting
New – Flat File Sink.
Player.log was chosen as a filename, without a header.
Formatters are used to define how a single log entry had to look. By default a
Text Formatter was provided, which included extensive information. To have an overview log file, a new formatter was added by right clicking
Formatters and selecting
New – Text Formatter. The template for this
Simple Text Formatter was the following:
{severity}
[{timestamp}]: {message}
Finally a new destination was added by right clicking the
Player category and selecting
New – Destination. This destination was configured to use the
Simple Text Formatter together with the
Player Flat File Sink.
After this, the
loggingconfiguration.config and
loggingdistributorconfiguration.config files had to be copied in the
Post-build event as well. At this point, the application had implemented a flexible logging strategy, where an administrator could easily decide to turn logging on or off and where the log output had to go to and which template had to be used.
To configure the solution,
Enterprise Library was used. This contained a
Configuration Application Block which allowed defining various configuration sources externally from the application. This approach gave to ability to switch from XML configuration files to a database without having to change anything in the code. Because of this, it was also possible to distribute the application, and let an administrator choose where it should read the configuration from. An additional advantage of using the application block was the ability to automatically detect when the configuration had changed and retrieve the new values.
The easiest way to implement configuration, was to create a new project which contained all the possible configuration sections in the solution. Each configuration section was defined by a different class.
For example, to make the port used by
Remoting in the application configurable, I created a class which contained this value, together with a public property for it. This class uses the
Xml namespace, because it was serialized to XML, and the application block uses the public properties to populate the configuration data.
A default constructor also had to be present for
XML Serialization.
The configuration data for the player was for example contained in the
PlayerData class, which looked like this:
using System;
using System.Xml.Serialization;
namespace MediaService.Configuration {
public class PlayerData {
private Int32 remotingPort;
[XmlElement("RemotingPort")]
public Int32 RemotingPort {
get { return this.remotingPort; }
set { this.remotingPort = value; }
} /* RemotingPort */
public PlayerData() { }
public PlayerData(Int32 remotingPort) {
this.remotingPort = remotingPort;
} /* PlayerData */
} /* PlayerData */
} /* MediaService.Configuration */
To use these values, a reference to the
Configuration project had to be added, together with a reference to
Microsoft.Practices.EnterpriseLibrary.Configuration. After this the configuration could be loaded with the following code:
using Microsoft.Practices.EnterpriseLibrary.Configuration;
namespace MediaService.Player {
public class PlayerService : System.ServiceProcess.ServiceBase {
private PlayerData configData = null;
private void LoadConfiguration() {
ConfigurationManager.ClearSingletonSectionCache("playerConfiguration");
try {
this.configData = ConfigurationManager.
GetConfiguration("playerConfiguration") as PlayerData;
} catch (Exception ex) {
this.configData = new PlayerData(4000);
}
And to receive notifications the following code had to be added:
protected override void OnStart(string[] args) {
ConfigurationManager.ConfigurationChanged += new
ConfigurationChangedEventHandler(ConfigurationManager_ConfigurationChanged);
} /* OnStart */
private void ConfigurationManager_ConfigurationChanged(object sender,
ConfigurationChangedEventArgs e) {
this.LoadConfiguration();
// Check new values and perform possible actions
} /* ConfigurationManager_ConfigurationChanged */
At this point, all code needed for configuration was done. Now the
Enterprise Library Configuration tool had to be used to configure the application’s configuration source.
First, a new application had to be defined by using
File – New Application. Then the
Configuration Application Block had to be added through
Action – New - Configuration Application Block. After this, a new configuration section was added by right clicking on the new application block and selecting
New – Configuration Section.
This new section was called
playerConfiguration, as it is in the code, and uses an
XML Storage Provider and an
Xml Serializer Transformer, both added by right clicking the new section and selecting them from the
New menu.
The only thing that still had to be changed was the
XML Storage Provider,
playerConfiguration.config had to be given as a
FileName. After this, the configuration had to be saved.

The XML file used for configuration was the following:
<?xml version="1.0" encoding="utf-8"?>
<playerConfiguration>
<xmlSerializerSection type="MediaService.Configuration.PlayerData,
MediaService.Configuration,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=null">
<PlayerData xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RemotingPort>4000</RemotingPort>
</PlayerData>
</xmlSerializerSection>
</playerConfiguration>
The only thing left to make sure the application loaded the configuration during testing, was to provide a
Post-build event that copied the configuration file. To do this, in the project’s properties, under the
Common Properties was a
Build Events menu, where it was possible to define the
Post-build event. The following had to be used to copy the
playerconfiguration.config file:
copy "$(ProjectDir)playerconfiguration.config" "$(TargetDir)" >Nul
When the application was started, it would call the
LoadConfiguration method, which would populate the
PlayerData class and provide all configuration settings of the application. If the configuration file would be changed when the application was running, the
ConfigurationChanged event would be raised and the new configuration would be used.
After everything was done on the server-side of the
Remoting implementation, inside the
Windows Service, it was time to add the consumer side. In the case of this project, the consumer was an
ASP.NET Webservice running on the same machine.
This required little effort. First,
System.Runtime.Remoting had to be referenced, together with the assembly containing the interface used for the controller object. After this it was possible retrieve the controller object with the following code:
private IPlayerServiceController GetPlayerServiceController() {
return (IPlayerServiceController)Activator.GetObject(
typeof(IPlayerServiceController),
String.Format("tcp://{0}:{1}/MediaServicePlayerController",
this.configData.RemotingHost,
this.configData.RemotingPort));
} /* GetPlayerServiceController */
In this solution, the webservice does not need to reference the assembly containing the real controller, but only an assembly that contains the interface. The real implementation is running on the server-side, as an instantiated, marshalled object.
When the instance got returned, it was possible to use it very simple, like this code:
[WebMethod(Description="Stop playing the queue.")]
public void Stop() {
this.GetPlayerServiceController().StopPlaying();
} /* Stop */
More Posts
Next page »