I finally decided to get a new laptop to support at my home development process. My previous laptop was a three year old IBM Think Pad. Unfortunately, trying to run Visual Studio 2008 (with many of the new additions) and Office 2007 was painfully slow. Basically, I found myself waiting 5-10 minutes between builds on large scale projects.
While researching which laptop to get, the hardware was the easy part. My dream choice was an Intel Core 2 Duo, 4 GB Ram and 200 GB @ 7200 rpm. The much harder question was which brand: IBM, Dell, Sony or another computer. After quite a bit of research, I decided why not a MAC?
One might think; how does one run Visual Studio on a Mac? Vmware fusion is the answer. If you have never tried developing on a virtual machine, it is must. Moreover, when you can run Windows Server 2008 and Vista Ultimate simultaneously to replicate a SOA environment is amazing. Furthermore, debugging the SOA environment is a breeze with the .NET remote debugger.
Another benefit of virtual machines is the ability to save states. The obvious reason is recovery; however, two other reasons are more useful in daily development. First, the ability to suspend a development session and restart, at a later time, exactly where you left off. Furthermore, the restarting of session seems faster than restarting the operating system and visual studio. Second, the ability pass a session to a fellow developer is quite useful. Basically, this saves quite a bit of time explaining setup procedures to another developer.
Finally, I choose Vmware over Parallels mainly because of the dual core support. The Unity view allows me to seamlessly browse the web in safari and program in visual studio. Though I don’t do much website design, I could imagine such a scenario could be quite useful.
All in all, I am very happy with my current enviorment.
Due to the fact my background is in financial markets (trading systems to be exact), I find my self continuously trying to scrounge up milliseconds by code improvements. My weapon of choice is parallel processing or otherwise called threading. Over the years it has been both my greatest asset any my most malevolent foe. Many have commented on the impeding doom of mutable states and many core processors in software design; hence functional programming.
I have aspiration to neither speak about functional programming nor give a class on threading best practices. Instead, I am interested in providing an easier ReaderWriterLock schematic; most likely to the joy of my team.
The “lock{}” keyword (or “SyncLock” keyword for VB.NET) is very useful and concise in its usage; though anyone trying to squeeze milliseconds knows the performance benefits of a ReaderWriterLock in many cases. (Stop here if the previous statement doesn’t make sense to you and go Google the ReaderWriterLock.) However, the implementation of a ReaderWriterLock requires much more code and can cause dead locks if implemented incorrectly.
Thus, I came up with the attached solution. It offers improvements on two fronts. One, it allows a user to retry a function N number of times before raising an exception. Second, it ensures the locks are acquired and released correctly.
I am not exactly thrilled with this design because the use of anonymous methods makes for a non simple solution. Nevertheless, I think it is better then writing the internalized code in ever method that needs to be locked. Finally, I have not performance tested this yet; but I will post later with results. public class ClassThanNeedsLocking
{
ReTryReaderWriterLock _rw = new ReTryReaderWriterLock();
private Dictionary<double, double> _valueMap;
public ClassThanNeedsLocking()
{
this._valueMap = new Dictionary<double, double>();
}
public void AddSomething(double key, double value)
{
ReTryReaderWriterLock.FunctionalityToLock temp = delegate
{
this._valueMap.Add(key, value);
};
this._rw.WriterLockFunction(temp, 100, 5, 10);
}
public double GetSomething(double key)
{
double value = 0;
ReTryReaderWriterLock.FunctionalityToLock temp = delegate
{
if (this._valueMap.TryGetValue(key, out value))
{
throw new ArgumentException("Key Does Not Exist.", "key");
}
};
this._rw.ReaderLockFunction(temp, 100, 5, 10);
return value;
}
}
public class ReTryReaderWriterLock
{
public delegate void FunctionalityToLock();
private delegate void RepeatTryLock(int timesTried);
private ReaderWriterLock _rw = new ReaderWriterLock();
private ILock _reader = new ReaderLock();
private ILock _writer = new WriterLock();
public void ReaderLockFunction(FunctionalityToLock function, int timeOutPerTry, int timesToTry, int timeToWaitBeforeTryingAgain)
{
LockFunction(function, timeOutPerTry, timesToTry, timeToWaitBeforeTryingAgain, this._reader);
}
public void WriterLockFunction(FunctionalityToLock function, int timeOutPerTry, int timesToTry, int timeToWaitBeforeTryingAgain)
{
LockFunction(function, timeOutPerTry, timesToTry, timeToWaitBeforeTryingAgain, this._writer);
}
private void LockFunction(FunctionalityToLock function, int timeOutPerTry, int timesToTry, int timeToWaitBeforeTryingAgain, ILock typeOfLock)
{
RepeatTryLock repeater = null;
repeater = delegate(int timesTried)
{
try
{
typeOfLock.Acquire(this._rw, timeOutPerTry);
function();
}
catch (ApplicationException)
{
if (timesTried < timesToTry)
{
Thread.Sleep(timeToWaitBeforeTryingAgain);
timesTried += 1;
repeater(timesTried);
return;
}
throw;
}
finally
{
typeOfLock.Release(this._rw);
}
};
repeater(0);
}
private interface ILock
{
void Acquire(ReaderWriterLock rw, int timeOutPerTry);
void Release(ReaderWriterLock rw);
}
private class ReaderLock : ILock
{
public void Acquire(ReaderWriterLock rw, int timeOutPerTry)
{
rw.AcquireReaderLock(timeOutPerTry);
}
public void Release(ReaderWriterLock rw)
{
if (rw.IsReaderLockHeld == true)
{
rw.ReleaseReaderLock();
}
}
}
private class WriterLock : ILock
{
public void Acquire(ReaderWriterLock rw, int timeOutPerTry)
{
rw.AcquireWriterLock(timeOutPerTry);
}
public void Release(ReaderWriterLock rw)
{
if (rw.IsWriterLockHeld == true)
{
rw.ReleaseWriterLock();
}
}
}
}
I am sure I have said this before; has anyone else noticed how little code I have written? I have quite a bit to talk about, so tonight I will just drop all my code and screen shots unaccompanied. Thereafter, we will spend the next few evening talking about exactly what was done.
First, I created the data contracts.

Second, I created the service contracts.

Third, I added a Silverlight browser project.

Fourth, I added the WPF XAML for the Silverlight front end.
<UserControl x:Class="DBinsor.Svc.WCF.Browser.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:grid ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="90" />
<RowDefinition Height="50*" />
<RowDefinition Height="50*" />
<RowDefinition Height="10" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<grid:DataGrid x:Name="CastleGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="1" Grid.Column="2"
MouseLeftButtonDown="CastleGrid_MouseLeftButtonDown" />
<grid:DataGrid x:Name="ContractGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="1" Grid.Column="1"
MouseLeftButtonDown="ContractGrid_MouseLeftButtonDown"/>
<grid:DataGrid x:Name="ComponentGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="2" Grid.Column="2"
MouseLeftButtonDown="ComponentGrid_MouseLeftButtonDown" />
<grid:DataGrid x:Name="ImplementationGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="2" Grid.Column="1" />
<grid:DataGrid x:Name="ComponentParametersGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="3" Grid.Column="2"
CanUserResizeColumns="True" />
<grid:DataGrid x:Name="ContractParametersGrid" AlternatingRowBackground="Beige"
AutoGenerateColumns="True" Grid.Row="3" Grid.Column="1"
CanUserResizeColumns="True" />
</Grid>
</UserControl>
Fifth, I hooked the WCF Service to the Silverlight browser.
using System;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;
using DBinsor.Svc.WCF.Browser.DatabaseProxy;
namespace DBinsor.Svc.WCF.Browser
{
public partial class Page : UserControl
{
DatabaseServiceContractClient _dscc;
Castle _selectedCastle;
Contract _selectedContract;
Component _selectedComponent;
public Page()
{
InitializeComponent();
this._dscc = new DatabaseServiceContractClient();
this._dscc.DemandCastlesCompleted
+= new EventHandler<DemandCastlesCompletedEventArgs>(_dscc_DemandCastlesCompleted);
this._dscc.DemandComponentParametersCompleted
+= new EventHandler<DemandComponentParametersCompletedEventArgs>(_dscc_DemandComponentParametersCompleted);
this._dscc.DemandComponentsCompleted
+= new EventHandler<DemandComponentsCompletedEventArgs>(_dscc_DemandComponentsCompleted);
this._dscc.DemandContractParametersCompleted
+= new EventHandler<DemandContractParametersCompletedEventArgs>(_dscc_DemandContractParametersCompleted);
this._dscc.DemandContractsCompleted
+= new EventHandler<DemandContractsCompletedEventArgs>(_dscc_DemandContractsCompleted);
this._dscc.DemandImplementationsCompleted
+= new EventHandler<DemandImplementationsCompletedEventArgs>(_dscc_DemandImplementationsCompleted);
LoadPrimaryTables();
}
private void LoadPrimaryTables()
{
this._dscc.DemandCastlesAsync();
this._dscc.DemandContractsAsync();
}
private void _dscc_DemandCastlesCompleted(object sender, DemandCastlesCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.CastleGrid.ItemsSource = e.Result;
}
private void _dscc_DemandComponentParametersCompleted(object sender, DemandComponentParametersCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.ComponentParametersGrid.ItemsSource = e.Result;
}
private void _dscc_DemandComponentsCompleted(object sender, DemandComponentsCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.ComponentGrid.ItemsSource = e.Result;
}
private void _dscc_DemandContractParametersCompleted(object sender, DemandContractParametersCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.ContractParametersGrid.ItemsSource = e.Result;
}
private void _dscc_DemandContractsCompleted(object sender, DemandContractsCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.ContractGrid.ItemsSource = e.Result;
}
private void _dscc_DemandImplementationsCompleted(object sender, DemandImplementationsCompletedEventArgs e)
{
if (e.Error != null)
{
HtmlPage.Window.Alert(e.Error.Message);
return;
}
if (e.Result.Count == 0)
{
return;
}
this.ImplementationGrid.ItemsSource = e.Result;
}
private void CastleGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object temp = CastleGrid.SelectedItem;
if (temp == null)
{
return;
}
this._selectedCastle = temp as Castle;
this._dscc.DemandComponentsAsync(this._selectedCastle);
}
private void ContractGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object temp = ContractGrid.SelectedItem;
if (temp == null)
{
return;
}
this._selectedContract = temp as Contract;
this._dscc.DemandImplementationsAsync(this._selectedContract);
this._dscc.DemandContractParametersAsync(this._selectedContract);
}
private void ComponentGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object temp = ComponentGrid.SelectedItem;
if (temp == null)
{
return;
}
this._selectedComponent = temp as Component;
this._dscc.DemandComponentParametersAsync(this._selectedComponent);
}
}
}
Sixth, I used LINQ to Extract Data from the Entity Framework.
using System.Linq;
namespace DBinsor.Svc.WCF.BusinessLogic
{
public static class DatabaseToDataContractGenerator
{
public static DataContracts.Castles GetCastles()
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
DataContracts.Castles ret = new DataContracts.Castles();
var dataCastles = from castle in
db.Castle
select castle;
foreach (DataAccess.Model.Castle dataCastle in dataCastles)
{
DataContracts.Castle serviceCastle =
new DataContracts.Castle();
serviceCastle.id = dataCastle.Id;
serviceCastle.name = dataCastle.Name;
ret.Add(serviceCastle);
}
return ret;
}
}
public static DataContracts.Components GetComponents(DataContracts.Castle castle)
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
int temp;
DataContracts.Components ret = new DataContracts.Components();
var dataComponents = from component in
db.Components
where component.Castle.Id == castle.id
select component;
foreach (DataAccess.Model.Components dataComponent in dataComponents)
{
DataContracts.Component serviceComponent =
new DataContracts.Component();
serviceComponent.id = dataComponent.Id;
int.TryParse(dataComponent.InitialPoolSize.ToString(), out temp);
serviceComponent.initialPoolSize = temp;
serviceComponent.inspectionBehavior = dataComponent.InspectionBehavior;
serviceComponent.lifestyle = dataComponent.Lifestyle;
int.TryParse(dataComponent.MaxPoolSize.ToString(), out temp);
serviceComponent.maxPoolSize = temp;
serviceComponent.Castle = castle;
serviceComponent.Implementation = new DataContracts.Implementation();
//todo: Add Implementation Name
ret.Add(serviceComponent);
}
return ret;
}
}
public static DataContracts.ComponentParameters GetComponentParameters(DataContracts.Component component)
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
DataContracts.ComponentParameters ret = new DataContracts.ComponentParameters();
var dataComponentParameters = from componentParameter in
db.ComponentParameters
where componentParameter.Components.Id == component.id
select componentParameter;
foreach (DataAccess.Model.ComponentParameters dataComponentParameter in dataComponentParameters)
{
DataContracts.ComponentParameter serviceComponentParameter =
new DataContracts.ComponentParameter();
serviceComponentParameter.Component = component;
serviceComponentParameter.overrideValue = dataComponentParameter.OverrideValue;
//todo: Add Contract Parameter Name
ret.Add(serviceComponentParameter);
}
return ret;
}
}
public static DataContracts.Contracts GetContracts()
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
DataContracts.Contracts ret = new DataContracts.Contracts();
var dataContracts = from contract in
db.Contracts
select contract;
foreach (DataAccess.Model.Contracts dataContract in dataContracts)
{
DataContracts.Contract serviceContract =
new DataContracts.Contract();
serviceContract.id = dataContract.Id;
serviceContract.contractNamespace = dataContract.Namespace;
serviceContract.contractInterface = dataContract.Interface;
ret.Add(serviceContract);
}
return ret;
}
}
public static DataContracts.Implementations GetImplementations(DataContracts.Contract contract)
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
DataContracts.Implementations ret = new DataContracts.Implementations();
var dataImplementations = from implementation in
db.Implementations
where implementation.Contracts.Id == contract.id
select implementation;
foreach (DataAccess.Model.Implementations dataImplementation in dataImplementations)
{
DataContracts.Implementation serviceImplementation =
new DataContracts.Implementation();
serviceImplementation.name = dataImplementation.Name;
serviceImplementation.Contract = contract;
ret.Add(serviceImplementation);
}
return ret;
}
}
public static DataContracts.ContractParameters GetContractParameters(DataContracts.Contract contract)
{
using (DataAccess.Model.Entities db =
new DataAccess.Model.Entities())
{
DataContracts.ContractParameters ret = new DataContracts.ContractParameters();
var dataContractParameters = from contractParameter in
db.ContractParameters
where contractParameter.Contracts.Id == contract.id
select contractParameter;
foreach (DataAccess.Model.ContractParameters dataContractParameter in dataContractParameters)
{
DataContracts.ContractParameter serviceContractParameter =
new DataContracts.ContractParameter();
serviceContractParameter.name = dataContractParameter.Name;
serviceContractParameter.defaultValue = dataContractParameter.DefaultValue;
serviceContractParameter.Contract = contract;
ret.Add(serviceContractParameter);
}
return ret;
}
}
}
}
Seventh, I had to add the CSDL, MSL and SSDL files to my host project to make things work. Still need to think about a better way to do this:
<connectionStrings>
<add name="DBinsor.Svc.WCF.DataAccess.Properties.Settings.WindsorDataBaseConnectionString"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\WindsorDataBase.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
</connectionStrings>Finally, Here is the End Product:
Both of these technologies are very powerful ways of implementing object to relational mapping. With LINQ to SQL, I feel it should be built on top of “views” so when one makes table changes the whole system doesn’t come crashing down. The Entity Framework seems to cover such scenarios in its mapping functionality.
However, neither seems to place nice in the n-tier model. That is, in which DLL should the EDMX or the DBML files belong? In one sense they do data access and in another they define business entities. On the one hand, I suppose one could put them in the data access layer and use business logic to convert those entities to ones defined in the business tier. Yet, that seems like a lot of work and bit un-refactored. On the other hand, we could put them in the business layer, but then we are doing data access from the business layer.
I would like to see a system where the data access is decoupled from the entities. For now, I am going to add these files to the data access layer. Furthermore, I am going to add the Data Contracts from my service layer to my business layer: not really happy about that. However, this will allow me the ability to use my business layer as a translator to expose my entities to the Silverlight frontend.
I could add the data access to my service implementation project, but I think it is better to do such translations in the business layer. Obviously, we could build duplicate entities in the business layer and translate twice, then again to much work and not that refactored.
I am using Windows XP Professional, Visual Studio 2008 Professional, IE 7.0 and Silverlight 2.0. The weird thing is I must delete my history every time in IE before I can view changes to my Silverlight application. I am assuming that is caching the XAP file in the browser and not reloading it when I make changes. I am sure there is a work around, but I have not had time to look for it. Any ideas?
It has been a couple weeks since my last post. As with many juggling family, career, socializing and hobbies can be quite a circus act. Nonetheless, the DBinsor solution has not yet reached a critical mass for usability.
It is great that one can pull the configuration from the database, but how does one put it there in the first place. Moreover, this process of insertion should be intuitive as well as allow for a holistic view of the data.
The end user of choice for DBinsor would be a system which utilized a plug in methodology meshed with a SOA topology. More specifically, one who utilizes services contracts where the implementation is defined by configuration settings. Thus utilizing DBinsor as a centralized configuration store should be quite appealing.
With this type of user in mind, a web user interface is the only sensible approach. For example, an administrator could seamlessly change configurations of any service from any computer with accessibility to the DBinsor server without installing a windows client.
We could have chosen web forms or the new model view controller framework; however Silverlight 2.0 seems the most intriguing. Moreover, we get the chance to work with XAML instead of HTML and Java Script. The “Learn” section has been quite helpful in the process of learning Silverlight.
We will post something once we have basic functionality working.
We uploaded the working code to the Code Gallery Site. This should allow readers of this blog the ability to see exactly what is happening underneath the hood. One very interesting use of this application is a centralized configuration repository. That is because of the parameters feature of the Windsor Library, a user should use those instead of a configuration file.
If anyone is interested in contributing to this project, please send me an email. The next features will include:
· A web GUI to access the database
· A windows application using reflection to auto generate data from an assembly
· Using card space to add security
· Exposing all the features of the container.
· Performance Enhancements
· And others.
We have also added Code Gallery to Navigation Section.
To test this, we decided to setup an interface and two derived classes. Then we added corresponding data to the database (we will build an intuitive graphical user interface eventually). Finally, we used the Container Singleton class to resolve our types and print out the results.
Class Diagram:

Database:
Windsor Component View
|
Lookup Name |
Namespace |
Contract |
Implementation |
Component Id |
Contract Id |
|
|
|
|
| | |