Here is the final solution to my problem. Credit to @pwzeus for his observations. This is an exact copy-and-paste of my test code from LINQPad:
var articles =
(from ch in ContentHistories
.Where(ch=> ch.CompareTag == new Guid("D3C38885-58AB-45CB-A19C-8EF48360F29D")
&& ch.AgainstTag == new Guid("5832933B-9AF9-4DEC-9D8D-DA5F211A5B53")
& ch.Created > DateTime.Now.AddDays(-3)) // Initial record filtering
select ch.Content) // Only return the XML Content column
.Elements("Article") // Get <Article> child elements
.Select(article => new {
Id = Convert.ToInt32(article.Element("Id").Value),
AcessionNumber = (string)article.Element("AcessionNumber").Value,
Headline = (string)article.Element("Headline").Value,
PublicationDate = Convert.ToDateTime(article.Element("PublicationDate").Value),
ArrivalDate = Convert.ToDateTime(article.Element("ArrivalDate").Value),
Source = (string)article.Element("Source").Value,
CopyRight = (string)article.Element("CopyRight").Value,
Language = (string)article.Element("Language").Value,
WordCount = String.IsNullOrEmpty(article.Element("WordCount").Value) ? 0 : Convert.ToInt32(article.Element("WordCount").Value),
Snippet = (string)article.Element("Headline").Value,
LeadParagraph = (string)article.Element("Headline").Value,
ContentGuid = new Guid(article.Element("ContentGuid").Value)
}) // Select and coerce data into new object
.Skip(5) // Skip records for paging in web UI
.Take(5) // Take only 1 page of records for display;
articles.Dump();
For the curious here is the T-SQL generated:
-- Region Parameters
DECLARE @p0 UniqueIdentifier = 'd3c38885-58ab-45cb-a19c-8ef48360f29d'
DECLARE @p1 UniqueIdentifier = '5832933b-9af9-4dec-9d8d-da5f211a5b53'
DECLARE @p2 DateTime = '2009-09-27 12:43:20.386'
-- EndRegion
SELECT [t0].[Content]
FROM [ContentHistory] AS [t0]
WHERE ([t0].[CompareTag] = @p0) AND ([t0].[AgainstTag] = @p1)
AND ([t0].[Created] > @p2)
It would have been nice too only retrieve as many rows as needed on the database side but for each row in ContentHistory
the Content
field contains an XML document with a variable number of <Article>
nodes. For example, if I .Skip(5).Take(5) on the SQL-side then I may have just skipped over 50 articles yet only return 5 if the rows contained the following article counts:
Row ArticleCount
=== ============
1 10
2 5
3 20
4 10
5 5
6 1
7 1
8 1
9 1
10 1