Introduction
I have been fascinated with using XMLDocument in C# applications for the past year. I have used XML for local storage and small applications such as Windows services. I like the way they can be easily searched using XPath queries and the way I can load the whole table into a web browser.
So, it struck me. Could I set up a XmlDocument to be a multiuser database? After all, XML is a schema for a hierarchical (as opposed to a relational) database. In my previous article, I showed how a single windows service could read and update a document using a mutex. But now I want multiple users to have simultaneous access to my document, just like a database.
The answer, of course is a web service.
The critical things are how can I load a resource once and how can I have multiple users access it without collisions.
Well the first part is taken care of by setting my XmlDocument in the class as a static member.
private static Pool xpd = new Pool(@"c:\xmlbase\pool.xml");
The second is taken care of by using a Mutex to act as a switch to my document. This way, I can read and change my documentation without collisions - just like it was a static member integer or other variable!
private static Mutex
mut = new Mutex();
There is a trick here.
You will notice that I do not instantiate an XmlDocument, that is because XmlDocument() does not have a constructor to take a file name in directly, it requires me to execute the Load method. And I don't want the web service to load the file each time it is called - I want it to load once, and then update continuously as long as the web service is running and in use!
I tried using a static constructor directly in the web service, but that loaded each time I called the web service when I tested it in the debugger.
So, I created a class called Pool:
public class Pool
{
public XmlDocument xd = new XmlDocument();
public Pool( string docname)
{
xd.Load ( docname );
}
}
and I instantiate that as a static member of my web service, called DataBourse.asmx.
So what does a database do that is interesting? Of course, it serves up data. I just want to be really simple here, and I'm sure we can keep extending this prototype, but for simplicities sake, lets just return one node -using SelectSingleNode - for each XPath query.
So here's my 'select' method:
[ WebMethod]
public string SelectFromPool(string xpathquery)
{
mut.WaitOne ();
XmlNode resultNode = xpd.xd.SelectSingleNode (xpathquery);
mut.ReleaseMutex ();
return resultNode.InnerText;
}
Then, of course we would want an 'update' method, and it's great to use the first method to help the second return a result:
[ WebMethod]
public string UpdateSelectedNodeInPool(string xpathquery, string updatetext)
{
mut.WaitOne ();
xpd.xd.SelectSingleNode (xpathquery). InnerText= updatetext;
mut.ReleaseMutex ();
return SelectFromPool(xpathquery);
}
You can have hours of fun calling UpdateSelectNodeInPool and seeing it updated in SelectFromPool. Load testing has just begun for me. I'm very curious to see how far I can push this little web service.
Well, it could go on and on.
I haven't implemented a Delete method yet, and at some point I'll want to persist the document back to disk (when and with what criteria, I do not yet know).