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 |
|
|
|
|
|
|
|
Test1 |
DBinsor.Svc.WCF.Client |
IMath |
Add |
1844d2e0-455e-4d44-a9ff-1c63f78e407b |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
|
Test1 |
DBinsor.Svc.WCF.Client |
IMath |
Subtract |
5c3ee79a-926c-4438-8391-44a437bd8f47 |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
Windsor Parameters View
|
Component Id |
Contract Id |
Parm Name |
Default |
Override |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5c3ee79a-926c-4438-8391-44a437bd8f47 |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
a |
1 |
13 |
|
5c3ee79a-926c-4438-8391-44a437bd8f47 |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
b |
2 |
NULL |
|
1844d2e0-455e-4d44-a9ff-1c63f78e407b |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
a |
1 |
NULL |
|
1844d2e0-455e-4d44-a9ff-1c63f78e407b |
0aa71152-91d4-4e8f-a4a0-4124a98e2851 |
b |
2 |
NULL |
Classes:
Test:
IMath proxy = ContainerSingleton.Instance.Resolve<Add, IMath>();
Console.WriteLine(proxy.Calculate().ToString());
proxy = ContainerSingleton.Instance.Resolve<Subtract, IMath>();
Console.WriteLine(proxy.Calculate().ToString());
Console.WriteLine(ContainerSingleton.Instance.Xml);
Result:
3
11
<configuration>
<components>
<component id="DBinsor.Svc.WCF.Client.Add"
service="DBinsor.Svc.WCF.Client.IMath, DBinsor.Svc.WCF.Client" type="DBinsor.Svc.WCF.Client.Add, DBinsor.Svc.WCF.Client">
<parameters>
<a>1</a>
<b>2</b>
</parameters>
</component>
<component id="DBinsor.Svc.WCF.Client.Subtract"
service="DBinsor.Svc.WCF.Client.IMath, DBinsor.Svc.WCF.Client" type="DBinsor.Svc.WCF.Client.Subtract, DBinsor.Svc.WCF.Client">
<parameters>
<a>13</a>
<b>2</b>
</parameters>
</component>
</components>
</configuration>
One thing we have found useful over the years is to wrap a service proxy in a public interface Dynamic Link Library. Though this in one sense may contradict the idea of Service Oriented Architecture (SOA); in another sense it holds up the idea of refactoring.
In this project, we have created a singleton that loads the configuration file from the database. Furthermore, this singleton aggregates Windsor Container for easy of accessibility throughout ones program. One draw back is (depending on usage) the load time of ones program may suffer due to Service / Database Access.
Previously, we stated that DBinsor required each class to implement an interface. Thus, we ensured this by added our custom resolve method in the singleton. public T Resolve<T, S>()
where T : class, S
{
return this._container.Resolve<S>(typeof(T).ToString()) as T;
}
In future releases of this library, we will add more methods to the singleton to provide access to other functionality of the Windsor Container.
Again, we used the factory methodology to allow for multiple sources for the Windsor Container. That is, we plan to allow a user to pick from our database service, an application configuration file, a web configuration file or a standalone xml file as their source for the singleton.
The public interface uses the “app.config” or the “web.config” files for three things: lookup name, resource source and service binding. Here is a sample:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="LookupName" value="Test1" />
<add key="ResourceSource" value="Database" />
</appSettings>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ConfigSvcEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:3837/DBinsor.Svc.WCF.Host/Configuration.svc"
binding="basicHttpBinding" bindingConfiguration="ConfigSvcEndPoint"
contract="ConfigurationServiceProxy.ConfigurationServiceContract"
name="ConfigSvcEndPoint" />
</client>
</system.serviceModel>
</configuration>
In the last post, we purposely did not address the core question of how does one generate the xml configuration from the database. This used to require quite a bit of code; however, we have LINQ (praise the Microsoft Gods). I am by no means a LINQ expert, nevertheless I know enough to make it work.
The code is pretty straight forward; we used LINQ to SQL to select all rows from the database where the lookup name equals our requested name. Then we used LINQ to XML to put those rows into an XML file. This was almost too trivial of a task. using System;
using System.Linq;
using System.Xml.Linq;
using DBinsor.Svc.WCF.BusinessEntities;
using DBinsor.Svc.WCF.DataAccess;
namespace DBinsor.Svc.WCF.BusinessLogic
{
public class ResourceFromDatabase : IResource
{
public ConfigurationEntity GenerateXml(ConfigurationEntity entity)
{
if (entity == null)
{
throw new ArgumentException("Configuration Entity Was Null.", "entity");
}
if (string.IsNullOrEmpty(entity.LookupName) == true)
{
throw new ArgumentException("Lookup Name Was Null or Empty.", "entity");
}
using (DBinsorViewDataContext windsorDataAccess =
new DBinsorViewDataContext())
{
entity.Xml = new XElement("configuration",
new XElement("components",
from components in windsorDataAccess.WindsorComponents
where components.LookupName == entity.LookupName
orderby components.ImplementationName
select new XElement("component",
AddRequiredAttributes("id", components.Namespace + "." + components.ImplementationName),
AddRequiredAttributes("service", components.Namespace + "." + components.ContractName + ", " + components.Namespace),
AddRequiredAttributes("type", components.Namespace + "." + components.ImplementationName + ", " + components.Namespace),
AddOptionalAttributes("inspectionBehavior", components.InspectionBehavior),
AddOptionalAttributes("lifestyle", components.Lifestyle),
AddOptionalAttributes("customLifestyleType", components.CustomLifestyleType),
AddOptionalAttributes("initialPoolSize", components.InitialPoolSize.ToString()),
AddOptionalAttributes("maxPoolSize", components.MaxPoolSize.ToString()),
AddParameters(components.ComponentId, components.ContractId)
)
)
);
}
return entity;
}
private static XAttribute AddRequiredAttributes(string name, string value)
{
return new XAttribute(name, value);
}
private static object AddOptionalAttributes(string name, string value)
{
if (string.IsNullOrEmpty(value) == true)
{
return null;
}
return new XAttribute(name, value);
}
private static XElement AddParameters(Guid componentId, Guid contractId)
{
using (DBinsorViewDataContext windsorDataAccess =
new DBinsorViewDataContext())
{
return new XElement("parameters",
from parameters in windsorDataAccess.WindsorParmaters
where (parameters.ComponentId == componentId && parameters.ContractId == contractId)
orderby parameters.ParmName
select new XElement(parameters.ParmName,
ReturnDefaultOrOverride(parameters.ParmDefault, parameters.OverrideValue))
);
}
}
private static string ReturnDefaultOrOverride(string defaultValue, string overrideValue)
{
if (string.IsNullOrEmpty(overrideValue) == false)
{
return overrideValue;
}
return defaultValue;
}
}
}
The only concern I have is in the “AddParameters” function; does it make a round trip to the database on every select? I think it probably does; thus this may be a huge performance bottleneck. However, first we should build for proof of concept. Then we can go back and optimize.
Quite shockingly, we have etched out an n-tier service oriented system without writing a single line of code. Moreover, we are following best practices to decouple the data layer, business layer, service layer and presentation layer. Generally, we do this for two reasons: one, to promote the idea of separation of concerns and two, to allow for future flexibility when addressing change sets.
The wiring process can be summed up as adding business entities and logic to link the data layer to the service layer. Business entities should be though of as objects that hold state. Business logic should be thought of functions or processes that affect business entities. This is gray definition, because in some cases business entities might have functionality. An example of a business object is a person; who has a name and an age. However, this person may have an internal process called heartbeat: thus the grayness.
We will define one business entity (for now) called “ConfigurationEntity”. This entity will have two properties: “LookupName” and “Xml”. The “LookupName” will be used to find the castle configuration in the database. The “Xml” will hold the dynamically generated xml configuration from the database.
Before we proceed, generally I would unit test at this point. Test Driven Development (TDD) states: we should write tests first then code. However, because it would require the use of mocks, I will refrain until a later post.
Next, we will use a factory pattern to generate the xml from the database. Again, we are choosing a design that provides for flexibility during future change sets. The factory uses an enumeration to decide which type of process to return.
Finally, we have to generate translators to and from our service layer data contracts to our business layer business entities. These translators will be used in our service implementation to allow access to our business logic.
Class Diagram:

Factory: namespace DBinsor.Svc.WCF.BusinessLogic
{
public static class ResourceFactory
{
public static IResource GenerateResouce(ResourceLocations location)
{
switch (location)
{
case ResourceLocations.Database:
return new ResourceFromDatabase();
default:
throw new ArgumentException("Location Not Supported.", "location");
}
}
}
}Finally, we have to generate translators to and from our service layer data contracts to our business layer business entities. These translators will be used in our service implementation to allow access to our business logic. namespace DBinsor.Svc.WCF.ServiceImplementation
{
public static class TConfigurationEntityAndConfigurationResponse
{
public static ConfigurationResponse Convert(ConfigurationEntity from)
{
ConfigurationResponse to = new ConfigurationResponse();
to.ConfigurationPart = new ConfigurationPart();
to.ConfigurationPart.XmlConfiguration = new XmlConfiguration();
to.ConfigurationPart.XmlConfiguration.Config = from.Xml.ToString();
return to;
}
}
}namespace DBinsor.Svc.WCF.ServiceImplementation
{
public static class TConfigurationEntityAndConfigurationRequest
{
public static ConfigurationEntity Convert(ConfigurationRequest from)
{
return new ConfigurationEntity(from.CastleId.LookupName);
}
}
}namespace DBinsor.Svc.WCF.ServiceImplementation
{
public partial class ConfigurationService
{
public override ConfigurationResponse GetConfigurationDemand(ConfigurationRequest request)
{
IResource businessLogic = ResourceFactory.GenerateResouce(ResourceLocations.Database);
return TConfigurationEntityAndConfigurationResponse.Convert(
businessLogic.GenerateXml(
TConfigurationEntityAndConfigurationRequest.Convert(
request)));
}
}
}
At first glance these two new data access technologies seem to fulfill a common purpose. Though, from my basic understanding the ADO.NET Entity Framework [EF] acts more like an Object Relational Mapping [ORM] tool, where as the LINQ to SQL [LTOS] acts similar to an ADO.NET Dataset. This is my first observation and will most likely be discredited through further inspection.
Functionally, we are trying to use a technology to extract, insert, modify and delete from our database. Thus, it seems either technology would be well suited. For a production system, we would lean towards LTOS because EF is still in a beta 3 version. However, because we view this project as a learning exercise, we will employee both technologies.
Due to the fact the EF is much more like an ORM; we will use it for our data access to the tables of the database. Consequently, we will use LTOS for the data access associated with the views of the database. Basically, the idea is if we change the underlying table structure, our business object to relational mapping should not have to change.
In the above example, this should hold true (pending that EF does have a flexible Object to Relational Mapping portion). We will leave this argument unjustified for the moment, because most likely we will have to change the database later on.
ADO.NET Entity Framework Table Map:

LINQ to SQL View Map:

Component: SELECT dbo.Castle.Name AS LookupName, dbo.Contracts.Namespace, dbo.Implementations.Id, dbo.Contracts.Interface AS ContractName,
dbo.Implementations.Name AS ImplementationName, dbo.Components.InspectionBehavior, dbo.Components.Lifestyle,
dbo.Components.CustomLifestyleType, dbo.Components.InitialPoolSize, dbo.Components.MaxPoolSize, dbo.Components.Id AS ComponentId,
dbo.Contracts.Id AS ContractId
FROM dbo.Castle INNER JOIN
dbo.Components ON dbo.Castle.Id = dbo.Components.CastleId INNER JOIN
dbo.Implementations ON dbo.Components.ImplementationId = dbo.Implementations.Id INNER JOIN
dbo.Contracts ON dbo.Implementations.ContractId = dbo.Contracts.Id
Parameter: SELECT dbo.Components.Id AS ComponentId, dbo.Contracts.Id AS ContractId, dbo.ContractParameters.Name AS ParmName,
dbo.ContractParameters.DefaultValue AS ParmDefault, dbo.ComponentParameters.OverrideValue
FROM dbo.Components INNER JOIN
dbo.Implementations ON dbo.Components.ImplementationId = dbo.Implementations.Id INNER JOIN
dbo.Contracts ON dbo.Implementations.ContractId = dbo.Contracts.Id INNER JOIN
dbo.ContractParameters ON dbo.Contracts.Id = dbo.ContractParameters.ContractId LEFT OUTER JOIN
dbo.ComponentParameters ON dbo.Components.Id = dbo.ComponentParameters.ComponentId AND
dbo.ContractParameters.Id = dbo.ComponentParameters.ContractParameterId
Upon those who step into the same rivers flow other and yet other waters.
All things . . . are in flux like a river.
In my estimation, embracing change has revolutionized our conception of software architecture. With the advent of agile methodologies, we are consistently designing for change. Moreover, my team develops core functionality, deploys and welcomes change requests.
The question then becomes how does one code for change? Some of today’s biggest buzz words can give a clue: Test Driven Development (TDD), Domain Driven Design (DDD), Inversion of Control (IOC) and Service Oriented Architecture (SOA).
Test Driven Development, used correctly, can mitigate bugs during the implementation of change sets. Furthermore, DDD specifies a guide to use design patterns to implement loosely couple objects. In the same vein Inversion of Control, as shown in earlier posts, greatly reduces dependencies between objects. Finally, Service Oriented Architecture defines architecture to house loosely coupled systems.
In summation, we should embrace change throughout our design, implementation, deployment and changes set resolution.
I normally utilize the “Web Service Software Factory” to structure and implement my services. This package greatly decreases the time spent on the mundane tasks of exposing your business logic to the service layer.
One could argue that exposing business logic is quite simple, add a WCF service to your project and write your business logic in the *.svc file. However, we are here to write loosely coupled code. To this end, one can use multiple dynamic link libraries (.dll) to organize one code. Moreover, by judicially choosing where objects belong, one can apply the principles of separations of concerns.
The “hands on lab” for the web service factory is top notch. The modeling edition allows one to use a graphical approach to define data and services contacts quickly and correctly. Below are the data contract and the service contract files needed to expose a service with a DBinsor configuration file. Furthermore, I have included the projects contained in the solution file.
Data Contract:

Service Contract:

Solution:
The MSDN Code Gallery is finally setup. Prior to uploading a code sample, I would like to make a bit of headway in the documentation process.
Prior to starting this conversation, I will make the assumption that one has completed the “Getting Started Project”. Moreover, in the RC3 Documentation, I would recommend reading the “Concepts” and “User Guides” sections.
Last week I uploaded a database diagram without much explanation. I plan to rectify that shortcoming in this post. When perusing the Castle Windsor documentation, the Windsor configuration reference was extremely helpful in the design of the database.
Reading the tags in a top down manner, I decided the “includes tag” was not necessary in a database scenario. The “includes tag” is useful when one does not want to keep all configurations in one file. However, since we are keeping all configurations in a centralized database, the use of multiple configuration files is unnecessary. Similarly speaking, “global properties” are superfluous because of the database. However, the conception of “global properties” will be addressed on the database graphical user interface (GUI).
“Facilities” are very powerful in that they allow one to extend the container. Nonetheless, they are out of scope in this preliminary version of D-Binsor. Similarly, the concept of “interceptors” will be left for future version of this library.
The heart and soul of this configuration file lies in the use of “components” coupled with “parameters”. With this in mind, the first table I created was the Contracts Table.
In general, I create a primary key, “Id”, for all my tables to make table to table relationships easier. Many would not name the primary key for each table the same, though I found with LINQ to SQL to find the unique identifies in the corresponding object is much easier.
In the theme of trying to be succinct, I will explain the key design choices I made. My first large choice was that every implementation must have a contract. Windsor does allow for one to register classes which have no associated interface. However, I feel that in a large scale SOA systems, where “D-Binsor” will be most useful, there is very little drawback to interface programming. Furthermore, the extensibility benefits from interface programming, for example “Mocking”, are quite compelling.
This decision allows for function parameters to only be defined on a contract basis. Thus, we have concluded the right side of the diagram. Before we discuss the left side, one issue with this design is that one could create two contracts in the same namespace with the same signature and receive no database warning. Obviously, that is unacceptable in the programming space [we will have to tackle this problem in the business layer].
One of the goals, beyond data storage, of a database should be data integrity. That is the database should not allow one to enter data which breaks business rules.
The left side of the diagram allows one or more castle configuration files to utilize the contract implementation structure defined above. Generally, one would create a new configuration file by adding data to the castle table. From there one could register components and component parameters to generate the correct configuration file.
To reiterate, one of the goals of a database should be data integrity. In that vein, we should utilize non-null foreign key relationships. For example, the implementation table must have a non-null contract id. Moreover, we should use a unique key when necessary. Though it is not visible in the diagram, in the contract parameters table the combination of the contract id and name fields should be unique.
We have decided to upload the source code for this project to the MSDN Code Gallery. The code gallery site should be functional by April 6th, 2008. If you have an interest in joining this project please contact me, by email, through the blog site.
Here is my preliminary table schema. Tomorrow we will probe into how my assumptions influenced its design.

A well written program must implore the services of persistence. Many would argue not in all cases; I disagree. I personally cannot think of a program that would not benefit from a configuration file instead of hard coding settings. Yes, the configuration file is a means of persisting load settings. Moreover, event logs are also crucial to find user aborted exceptions.
Though most would think database, xml file or file system, my view of persistence is anything that allows continuity between sessions of you application. Before I delve deeply into what SQL Express can provide to this application [my next blog entry], I would like explore the two aforementioned concepts.
First, one should use an external configuration source to abstract ones code. The avoidance of recompilation and deployment provides for agility and stability. We will see later how I see Castle Windsor helping in this process.
Second, never swallow exceptions. By swallowing exceptions, I mean try catch without alerting the user. Moreover, write the exception to the event log; lost exceptions don’t help the debugging process. In general one should throw an exception early and cleanly allow for appropriate remedies. This is concept best taught by example.
There are many takes on the agile development process: SCRUM, TDD and Extreme Programming to name a few. One of the most important, in my estimation, from the agile manifesto is: “Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.”
With this in mind, my first function is simply to design a database and extract a compatible IResource for the Castle Windsor Container. In actuality this process was quite trivial [a Sunday afternoon] with the new technologies of .Net 3.5. Moreover, it will take me much longer to explain what I did; than actually do it.
In my next post, I will delve into the database design.
These concepts have been around for quite a few years: from Martin Fowler’s description to this month’s MSDN magazine’s tutorial. Stefano Mazzocchi wrote: “IOC is about enforcing isolation.” Not many would argue that the n-tier architecture is a bad thing, however have you ever tried instantiating one class from the business tier by itself?
To facilitate such a scenario, the idea of dependency injection and containers comes into play. One example of such a tool for .Net is Castle Windsor. This open source project allows a user to “Separate Concerns” by injecting dependencies through an xml specification.
As with many, I have a love hate relationship with xml configuration files. For example, Oren Eini has created Binsor to combat his xml irritations. My thought is instead; let us put it in a database.
I plan to use some new interesting technologies to do this. The idea is to use SQL Express with LINQ to SQL to handle the object relational mapping. Then I will use LINQ to XML to auto generate an XML document [I could probably bypass the Xml Interpreter altogether if wanted]. From there I will use WCF to expose the generated xml as a service. Once this is done, we will talk about GUI’s to update the database.
So let’s get started.
I had a professor in graduate school who once said that Computer Science, as an educational institution, is backwards. Furthermore, he went on to say that in no other field do professors teach without practical experience. For example, a professor of trial law would not teach how to cross examine a defendant if one did not have the corresponding experience. Nor would a professor of surgery explain the procedure of a heart transplant, if one did not have multiple transplants under one’s belt.
Obviously, the previous statement is quite general and a bit drastic. Nonetheless, as I interview prospective employees I am very disheartened by their conceptual knowledge of the field.
Out stems a few questions:
How has our industry come to such a state?
How can we educate better?
As a .Net Developer, we are in a whirlwind of new ideas, technologies and practices. Thus, it is an exciting time as well as a crucial time to educate as we do along.
The purpose of my blog is to educate on ideas, technologies, and practices from my personal experiences.
|
Copyright © 2010 Yezdaan Baber. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme:
|
|