LINQ and XLinq Patterns

[Blog Map]  This blog is inactive.  New blog: EricWhite.com/blog

It's my opinion that LINQ and XLinq will benefit from having patterns named. The coding techniques are involved enough that we should have names for them. This is my first take on what the patterns should be. I'll be adding more in the future.

Some of these patterns may be too simple to be called patterns. I've had the suggestion of calling them idioms. Another idea is to call them "notations".

In any case, it is good to have names for them. For example, instead of telling another programmer, oh, to do that, the best way is to write a query expression, put parens around it, then dot into the Take operator, you can say, use the Query Dot pattern. It seems valuable to me, what's your opinion?

Also, anyone who has new ideas for patterns, please let me know - I'll add them.

Patterns associated with LINQ and XLinq:

Functional Construction Pattern

This is the pattern that looks like this:

XElement contacts =
new XElement("contacts",
new XElement("contact",
new XElement("name", "Patrick Hines"),
new XElement("phone", "206-555-0144"),
new XElement("address",
new XElement("street1", "123 Main St"),
new XElement("city", "Mercer Island"),
new XElement("state", "WA"),
new XElement("postal", "68042")
)
)
);

XLinq Transform Pattern

This pattern is a variation of the Functional Construction Pattern that describes the code that can process one XML document and create another XML document with a different shape:

XElement phoneList = new XElement("phonelist",
from c in contacts.Elements()
select new XElement("contact",
new XElement("phonelistname", (string)c.Element("name")),
new XElement("phonenumber", (string)c.Element("phone"))
)
);

Data-To-XML Transform Pattern

This pattern is another variation of the Functional Construction Pattern that describes the code that can process data from a variety of sources and generate an XML document with a specific shape. This pattern would include embedding DLinq queries inside functional construction.

string[] bugList = {
"fly",
"spider",
"beetle"
};
XElement blXml = new XElement("bugList",
from b in bugList
select new XElement("bug", b));

Explicit Dot Notation Pattern

This is the pattern for using the LINQ query operators directly:

var z =
contacts.Elements()
.Where(c => (string)c.Element("address")
.Element("state") == "WA")
.Select(c => (string)c.Element("name"));

Query Dot Pattern

This is a pattern where you surround a query expression with parentheses, then invoke via dot notation other query operators that are not part of query expressions. The following takes the first result of the query using the Take operator:

string[] bugList = {
"beetle",
"cockroach",
"fly",
"spider"
};
var z =
(from b in bugList
where b.CompareTo("c") > 0
select b)
.Take(1);

Namespace Concatenation Pattern

This is the pattern that takes the place of prefixes when constructing XML:

XNamespace myNs = "https://mycompany.com";
XElement contacts =
new XElement(myNs+"contacts",
new XElement(myNs+"contact",
new XElement(myNs+"name", "Patrick Hines"),
new XElement(myNs+"phone", "206-555-0144",
new XAttribute("type", "home")),
new XElement(myNs+"phone", "425-555-0145",
new XAttribute("type", "work")),
new XElement(myNs+"address",
new XElement(myNs+"street1", "123 Main St"),
new XElement(myNs+"city", "Mercer Island"),
new XElement(myNs+"state", "WA"),
new XElement(myNs+"postal", "68042")
)
)
);

LINQ Implementation Pattern

This is the pattern where you write extension methods that become query operators.

Minimalist Functional Construction Pattern

If you define some static methods:

static XElement E(XName a){return new XElement(a);}
static XElement E(XName a, object b){return new XElement(a, b);}
static XElement E(XName a, params object[] b){return new XElement(a, b);}
static XAttribute A(XName a, object b){return new XAttribute(a, b);}
static XAttribute A(XName a, params object[] b){return new XAttribute(a, b);}

Then you can do functional construction with a minimum of syntactic noise:

XElement contacts =
E("contacts",
E("contact",
E("name", "Patrick Hines"),
E("phone",
A("Type", "Home"),
"206-555-0144"),
E("address",
E("street1", "123 Main St"),
E("city", "Mercer Island"),
E("state", "WA"),
E("postal", "68042")
)
)
);