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.