Introduction
This is a sample project to create an Outlook type address book with LINQ and XML. It also shows how to use menu and toolbars in your Windows application.
Background
LINQ (Language Integrated Query) is a Microsoft .NET Framework component that adds native data querying capabilities to the .NET languages. It allows you to query collections like arraylist, List, etc. LINQ to XML is a new way to construct, write and read XML data in the .NET language of the developers’ choice. This new API simplifies working with XML data without having to resort to using additional language syntax like XPath or XSLT. LINQ to XML is not a replacement for any of the current DOMs or XML class libraries; LINQ to XML in many cases overlaps their functionality and aims to provide a superior developer experience, but existing code will continue to work. One aspect of LINQ to XML is that it supports writing Query Expressions and can be combined with any of the other LINQ technologies to create or use XML data as a source or destination format.
Using the Code
The Address Book is created in C# with XML as a database to store the contacts. Addition, deletion and updation of the records to this XML file is done with LINQ.
Most of the coding is easy to understand as you go through the sample project. I will explain how I use LINQ to work with my XML file.
Make sure you have a reference to System.LINQ
and System.XML.LINQ
in order to work with LINQ to XML.
If you go through the static
class XMLParse
, you will see that all the coding related to LINQ is done here. Let me explain how it works.
Create a new XDocument
class object like this:
XDocument xmlDoc = XDocument.Load(XMLFilePath);
This will represent your entire XML in the memory. So now we can query this xmlDoc
to retrieve the records like this:
var addresses = from Address in xmlDoc.Descendants("Address")
select new {
FirstName = Address.Element("FirstName").Value,
LastName = Address.Element("LastName").Value,
Email = Address.Element("Email").Value,
Address1 = Address.Element("Address1").Value,
Address2 = Address.Element("Address2").Value,
City = Address.Element("City").Value,
Country = Address.Element("Country").Value,
Zip = Address.Element("Zip").Value,
Phone1 = Address.Element("Phone1").Value,
Phone2 = Address.Element("Phone2").Value,
State = Address.Element("State").Value,
};
Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var
. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. Here our var
addresses will have the following properties like FirstName
, LastName
....State
. Their values are filled from the elements of XML. A point to note here is that these var
addresses will act like a collection which will have a collection of objects and each object will have those properties. So now if you want to fill your List
with objects of the contacts
class, this is how you do it:
foreach (var address in addresses)
{
Contacts contact = new Contacts();
contact.FName = address.FirstName;
contact.LName = address.LastName;
contact.Email = address.Email;
contact.Address1 = address.Address1;
contact.Address2 = address.Address2;
contact.City = address.City;
contact.State = address.State;
contact.Country = address.Country;
contact.Phone1 = address.Phone1;
contact.Phone2 = address.Phone2;
ContactList.Add(contact);
}
Add Contact
Look at the AddContact
function of the XMLParse
class. To add a new contact, create a new XElement
and add it to the Root
node of your XDocument
which is xmlDoc
. The first parameter is the main node and from the second parameters, it will be XElement
s which will go inside this main node.
xmlDoc.Root.Add(
new XElement("Address",
new XElement("FirstName", contact.FName),
new XElement("LastName", contact.LName),
new XElement("Email", contact.Email),
new XElement("Address1", contact.Address1),
new XElement("Address2", contact.Address2),
new XElement("City", contact.City),
new XElement("Country", contact.Country),
new XElement("Zip", contact.Zip),
new XElement("Phone1", contact.Phone1),
new XElement("Phone2", contact.Phone2),
new XElement("State", contact.State)
));
Once you have added the new XElement
, it is added to the XML document in the memory. We need to update the main XML file on the disk. So:
xmlDoc.Save(XMLFilePath);
Update Contact
I have designed with the email address to be the primary key. So to update, we will match the email address and then update that respective XElement
. So let's say, I have the email address which needs to be updated. Go ahead and get the XElement
from your in memory xmlDoc
:
XElement element = xmlDoc.Root.Elements("Address").Where(r => (
string)r.Element("Email") == contact.Email).FirstOrDefault();
This will return the element where the email address matched. FirstOrDefault()
will return the first occurrence where it matched or the default value.
Use the SetElementValue
function of XElement
class to update the value like this:
if (element != null)
{
element.SetElementValue("FirstName", contact.FName);
element.SetElementValue("LastName", contact.LName);
element.SetElementValue("Email", contact.Email);
element.SetElementValue("Address1", contact.Address1);
element.SetElementValue("Address2", contact.Address2);
element.SetElementValue("City", contact.City);
element.SetElementValue("Country", contact.Country);
element.SetElementValue("Zip", contact.Zip);
element.SetElementValue("Phone1", contact.Phone1);
element.SetElementValue("Phone2", contact.Phone2);
element.SetElementValue("State", contact.State);
xmlDoc.Save(XMLFilePath);
}
Delete Contact
Delete will work in the same way as update works. But in this case, we will query the xmlDoc
to get the element and then use the remove
function to remove the element.
XElement element = xmlDoc.Root.Elements("Address").Where(r => (string)r.Element(
"Email") == emailAddress).FirstOrDefault();
if(element!=null)
element.Remove();
Points of Interest
LINQ is a really cool way of working with XML and SQL. It makes a developer's life quite easy. Also this address book sample is a complete independent sample. You can create a DLL of this project and can use it with any of your existing applications.
History
- 28th August, 2009: Initial post